diff --git a/.ci/deploy-mac.sh b/.ci/deploy-mac.sh index 930a87eee2..0b8c1994e0 100755 --- a/.ci/deploy-mac.sh +++ b/.ci/deploy-mac.sh @@ -31,21 +31,18 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \ # Download translations mkdir -p "rpcs3.app/Contents/translations" -ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \ - | grep "browser_download_url" \ - | grep "RPCS3-languages.zip" \ - | cut -d '"' -f 4) -if [ -z "$ZIP_URL" ]; then - echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations." -else - echo "Downloading translations from: $ZIP_URL" - curl -L -o translations.zip "$ZIP_URL" || { - echo "Failed to download translations.zip. Continuing without translations." - exit 0 - } - unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1 || \ +ZIP_URL="https://github.com/RPCS3/rpcs3_translations/releases/latest/download/RPCS3-languages.zip" +echo "Downloading translations from: $ZIP_URL" +if curl -fsSL "$ZIP_URL" -o "translations.zip"; then + echo "Successfully downloaded translations." + if unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1; then + rm -f translations.zip + else echo "Failed to extract translations.zip. Continuing without translations." - rm -f translations.zip + rm -f translations.zip + fi +else + echo "Warning: Failed to download translations. Skipping..." fi # Copy Qt translations manually diff --git a/3rdparty/curl/CMakeLists.txt b/3rdparty/curl/CMakeLists.txt index 2b725169f9..0079315267 100644 --- a/3rdparty/curl/CMakeLists.txt +++ b/3rdparty/curl/CMakeLists.txt @@ -7,24 +7,24 @@ if(USE_SYSTEM_CURL) target_link_libraries(3rdparty_libcurl INTERFACE CURL::libcurl) else() message(STATUS "RPCS3: building libcurl + wolfssl submodules") - set(BUILD_CURL_EXE OFF CACHE BOOL "Set to ON to build curl executable.") - set(BUILD_STATIC_CURL OFF CACHE BOOL "Set to ON to build curl executable with static libcurl.") - set(BUILD_STATIC_LIBS ON CACHE BOOL "Set to ON to build static libcurl.") - set(BUILD_SHARED_LIBS OFF CACHE BOOL "Set to ON to build shared libcurl.") + set(BUILD_CURL_EXE OFF CACHE INTERNAL "") + set(BUILD_STATIC_CURL OFF CACHE INTERNAL "") + set(BUILD_STATIC_LIBS ON CACHE INTERNAL "") + set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "") find_package(WolfSSL REQUIRED) - set(CURL_USE_WOLFSSL ON CACHE BOOL "enable wolfSSL for SSL/TLS") - set(CURL_USE_OPENSSL OFF CACHE BOOL "Use OpenSSL code. Experimental") - set(HTTP_ONLY ON CACHE BOOL "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)") - set(USE_LIBIDN2 OFF CACHE BOOL "Use libidn2 for IDN support") # Disabled because MacOS CI doesn't work otherwise - set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") - option(CURL_DISABLE_INSTALL "Disable installation targets" ON) + set(CURL_USE_WOLFSSL ON CACHE INTERNAL "") + set(CURL_USE_OPENSSL OFF CACHE INTERNAL "") + set(HTTP_ONLY ON CACHE INTERNAL "") + set(USE_LIBIDN2 OFF CACHE INTERNAL "") # Disabled because MacOS CI doesn't work otherwise + set(CURL_CA_PATH "none" CACHE INTERNAL "") + set(CURL_DISABLE_INSTALL ON CACHE INTERNAL "") if(WIN32) - set(ENABLE_UNICODE ON CACHE BOOL "enable Unicode") + set(ENABLE_UNICODE ON CACHE INTERNAL "") endif() - set(CURL_USE_LIBSSH2 OFF CACHE BOOL "Use libSSH2") - set(CURL_USE_LIBPSL OFF CACHE BOOL "Use libPSL") - option(BUILD_TESTING "Build tests" OFF) - option(BUILD_EXAMPLES "Build libcurl examples" OFF) + set(CURL_USE_LIBSSH2 OFF CACHE INTERNAL "") + set(CURL_USE_LIBPSL OFF CACHE INTERNAL "") + set(BUILD_TESTING OFF CACHE INTERNAL "") + set(BUILD_EXAMPLES OFF CACHE INTERNAL "") add_subdirectory(curl EXCLUDE_FROM_ALL) diff --git a/3rdparty/libpng/libpng b/3rdparty/libpng/libpng index 95ab3fdca8..3061454d98 160000 --- a/3rdparty/libpng/libpng +++ b/3rdparty/libpng/libpng @@ -1 +1 @@ -Subproject commit 95ab3fdca83ea294efd3b092e9a53c5a39886444 +Subproject commit 3061454d980de7d53608f594194cfac722721d2a diff --git a/3rdparty/version_check.sh b/3rdparty/version_check.sh index e0632da3e7..7947a006c1 100644 --- a/3rdparty/version_check.sh +++ b/3rdparty/version_check.sh @@ -119,7 +119,8 @@ echo -e "\n\nResult:\n" # Find the max length of the paths (before '->') max_len=0 -while IFS='->' read -r left _; do +while read -r line; do + left="${line%%->*}" len=$(echo -n "$left" | wc -c) if (( len > max_len )); then max_len=$len @@ -127,8 +128,10 @@ while IFS='->' read -r left _; do done < "$resultfile" # Print with padding so '->' lines up -while IFS='->' read -r left right; do - right=$(echo "$right" | sed 's/^[[:space:]]*>*[[:space:]]*//') +while read -r line; do + left="${line%%->*}" + right="${line#*->}" + right=$(echo "$right" | sed 's/^[[:space:]]*//') printf "%-${max_len}s -> %s\n" "$left" "$right" done < "$resultfile" diff --git a/3rdparty/wolfssl/CMakeLists.txt b/3rdparty/wolfssl/CMakeLists.txt index cf1a66a1f5..2c19c37d2f 100644 --- a/3rdparty/wolfssl/CMakeLists.txt +++ b/3rdparty/wolfssl/CMakeLists.txt @@ -4,23 +4,22 @@ if(USE_SYSTEM_WOLFSSL) add_library(wolfssl INTERFACE) target_link_libraries(wolfssl INTERFACE PkgConfig::WolfSSL) else() - option(WOLFSSL_TLS13 "Enable wolfSSL TLS v1.3 (default: enabled)" OFF) - set(WOLFSSL_SHA3 ON CACHE STRING "Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)") - set(WOLFSSL_SHAKE256 ON CACHE STRING "Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)") - option(WOLFSSL_BASE64_ENCODE "Enable Base64 encoding (default: enabled on x86_64)" OFF) - option(WOLFSSL_DES3 "Enable DES3 (default: disabled)" ON) - option(WOLFSSL_PWDBASED "Enable PWDBASED (default: disabled)" ON) - option(WOLFSSL_FAST_MATH "Enable fast math ops (default: disabled)" ON) - option(WOLFSSL_EXAMPLES "Enable examples (default: enabled)" OFF) - option(WOLFSSL_CRYPT_TESTS "Enable Crypt Bench/Test (default: enabled)" OFF) - option(WOLFSSL_ASYNC_THREADS "Enable Asynchronous Threading (default: enabled)" OFF) - option(WOLFSSL_BUILD_OUT_OF_TREE "Don't generate files in the source tree (default: yes)" ON) - option(WOLFSSL_SNI "Enable SNI (default: disabled)" ON) - option(WOLFSSL_OPENSSLEXTRA "Enable extra OpenSSL API, size+ (default: disabled)" ON) - option(WOLFSSL_HARDEN "Enable Hardened build, Enables Timing Resistance and Blinding (default: enabled)" OFF) - option(WOLFSSL_ALT_CERT_CHAINS "Enable support for Alternate certification chains (default: disabled)" ON) + set(WOLFSSL_TLS13 OFF CACHE INTERNAL "") + set(WOLFSSL_SHA3 ON CACHE INTERNAL "") + set(WOLFSSL_SHAKE256 ON CACHE INTERNAL "") + set(WOLFSSL_BASE64_ENCODE OFF CACHE INTERNAL "") + set(WOLFSSL_DES3 ON CACHE INTERNAL "") + set(WOLFSSL_PWDBASED ON CACHE INTERNAL "") + set(WOLFSSL_FAST_MATH ON CACHE INTERNAL "") + set(WOLFSSL_EXAMPLES OFF CACHE INTERNAL "") + set(WOLFSSL_CRYPT_TESTS OFF CACHE INTERNAL "") + set(WOLFSSL_ASYNC_THREADS OFF CACHE INTERNAL "") + set(WOLFSSL_BUILD_OUT_OF_TREE ON CACHE INTERNAL "") + set(WOLFSSL_SNI ON CACHE INTERNAL "") + set(WOLFSSL_OPENSSLEXTRA ON CACHE INTERNAL "") + set(WOLFSSL_ALT_CERT_CHAINS ON CACHE INTERNAL "") add_subdirectory(wolfssl EXCLUDE_FROM_ALL) - target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_NO_OPTIONS_H) + target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_USE_OPTIONS_H) endif() diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp index ec2b4ca1c9..f242bd6172 100644 --- a/Utilities/Config.cpp +++ b/Utilities/Config.cpp @@ -479,8 +479,9 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str { case type::node: { - if (data.IsScalar() || data.IsSequence()) + if (!data.IsMap()) { + cfg_log.error("node node is not a map"); return false; } @@ -491,17 +492,22 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str if (!pair.first.IsScalar()) continue; // Find the key among existing nodes - for (const auto& node : static_cast(rhs).get_nodes()) - { - if (node->get_name() == pair.first.Scalar()) - { - if (!decode(pair.second, *node, dynamic, strict) && strict) - { - success = false; - } + const auto& nodes = static_cast(rhs).get_nodes(); + const auto it = std::find_if(nodes.cbegin(), nodes.cend(), [&pair](const auto& node) { return ensure(node)->get_name() == pair.first.Scalar(); }); - break; + if (it == nodes.cend()) + { + if (strict) + { + cfg_log.error("Unknown key found: '%s'", pair.first.Scalar()); + success = false; } + continue; + } + + if (!decode(pair.second, *ensure(*it), dynamic, strict) && strict) + { + success = false; } } @@ -513,7 +519,10 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str if (YAML::convert::decode(data, values)) { - rhs.from_list(std::move(values)); + if (!rhs.from_list(std::move(values)) && strict) + { + return false; + } } break; @@ -523,6 +532,7 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str { if (!data.IsMap()) { + cfg_log.error("map node is not a map"); return false; } @@ -540,8 +550,9 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str } case type::log: { - if (data.IsScalar() || data.IsSequence()) + if (!data.IsMap()) { + cfg_log.error("log node is not a map"); return false; } @@ -549,7 +560,18 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str for (const auto& pair : data) { - if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue; + if (!pair.first.IsScalar() || !pair.second.IsScalar()) + { + if (strict) + { + if (!pair.first.IsScalar()) + cfg_log.error("Key in map is not a scalar"); + else + cfg_log.error("Value in map is not a scalar. key='%s'", pair.first.Scalar()); + return false; + } + continue; + } u64 value; if (!cfg::try_to_enum_value(&value, &fmt_class_string::format, pair.second.Scalar(), pair.first.Scalar()) && strict) @@ -567,6 +589,7 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str { if (!data.IsMap()) { + cfg_log.error("device node is not a map"); return false; } @@ -574,13 +597,35 @@ bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool str for (const auto& pair : data) { - if (!pair.first.IsScalar() || !pair.second.IsMap()) continue; + if (!pair.first.IsScalar() || !pair.second.IsMap()) + { + if (strict) + { + if (!pair.first.IsScalar()) + cfg_log.error("Key in device map is not a scalar"); + else + cfg_log.error("Value in device map is not a map. key='%s'", pair.first.Scalar()); + return false; + } + continue; + } device_info info{}; for (const auto& key_value : pair.second) { - if (!key_value.first.IsScalar() || !key_value.second.IsScalar()) continue; + if (!key_value.first.IsScalar() || !key_value.second.IsScalar()) + { + if (strict) + { + if (!key_value.first.IsScalar()) + cfg_log.error("Key in device info map is not a scalar"); + else + cfg_log.error("Value in device map is not a scalar. key='%s'", key_value.first.Scalar()); + return false; + } + continue; + } if (key_value.first.Scalar() == "Path") info.path = key_value.second.Scalar(); diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index 51e5ed6a33..d7073a4e47 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -520,10 +520,11 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr dirName return CELL_GAMEDATA_ERROR_PARAM; } - if (!fs::create_path(vfs::get(usrdir))) - { - return {CELL_GAME_ERROR_ACCESS_ERROR, usrdir}; - } + // Nuked until correctly reversed engineered + //if (!fs::create_path(vfs::get(usrdir))) + //{ + // return {CELL_GAME_ERROR_ACCESS_ERROR, usrdir}; + //} } // Nuked until correctly reversed engineered diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp index 9147b7e5c5..d8e60b7592 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp @@ -239,7 +239,7 @@ namespace rsx home_menu_settings_performance_overlay::home_menu_settings_performance_overlay(s16 x, s16 y, u16 width, u16 height, bool use_separators, home_menu_page* parent) : home_menu_settings_page(x, y, width, height, use_separators, parent, get_localized_string(localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY)) { - add_checkbox(&g_cfg.video.perf_overlay.perf_overlay_enabled, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE); + add_checkbox(&g_cfg.video.perf_overlay.enabled, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE); add_checkbox(&g_cfg.video.perf_overlay.framerate_graph_enabled, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMERATE_GRAPH); add_checkbox(&g_cfg.video.perf_overlay.frametime_graph_enabled, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMETIME_GRAPH); @@ -258,7 +258,7 @@ namespace rsx add_float_slider(&g_cfg.video.perf_overlay.margin_y, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_MARGIN_Y, " %", 0.25f); add_unsigned_slider(&g_cfg.video.perf_overlay.font_size, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_FONT_SIZE, " px", 1); add_unsigned_slider(&g_cfg.video.perf_overlay.opacity, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_OPACITY, " %", 1); - add_checkbox(&g_cfg.video.perf_overlay.perf_overlay_use_window_space, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_USE_WINDOW_SPACE); + add_checkbox(&g_cfg.video.perf_overlay.use_window_space, localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_USE_WINDOW_SPACE); apply_layout(); } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp index 635833c9d8..afaf7eb772 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp @@ -934,7 +934,7 @@ namespace rsx auto& perf_settings = g_cfg.video.perf_overlay; auto perf_overlay = manager->get(); - if (perf_settings.perf_overlay_enabled) + if (perf_settings.enabled) { if (!perf_overlay) { @@ -949,7 +949,7 @@ namespace rsx perf_overlay->set_font(perf_settings.font); perf_overlay->set_font_size(perf_settings.font_size); perf_overlay->set_margins(static_cast(perf_settings.margin_x.get()), static_cast(perf_settings.margin_y.get()), perf_settings.center_x.get(), perf_settings.center_y.get()); - perf_overlay->use_window_space = perf_settings.perf_overlay_use_window_space.get(); + perf_overlay->use_window_space = perf_settings.use_window_space.get(); perf_overlay->set_opacity(perf_settings.opacity / 100.f); perf_overlay->set_body_colors(perf_settings.color_body, perf_settings.background_body); perf_overlay->set_title_colors(perf_settings.color_title, perf_settings.background_title); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 33fd4a662b..425985c5ba 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3414,7 +3414,7 @@ namespace rsx current_display_buffer = buffer; m_queued_flip.emu_flip = true; m_queued_flip.in_progress = true; - m_queued_flip.skip_frame |= g_cfg.video.disable_video_output && !g_cfg.video.perf_overlay.perf_overlay_enabled; + m_queued_flip.skip_frame |= g_cfg.video.disable_video_output && !g_cfg.video.perf_overlay.enabled; flip(m_queued_flip); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 40a87fcab8..5a1c41072b 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -933,7 +933,7 @@ game_boot_result Emulator::GetElfPathFromDir(std::string& elf_path, const std::s return game_boot_result::invalid_file_or_folder; } -game_boot_result Emulator::BootGame(const std::string& path, const std::string& title_id, bool direct, cfg_mode config_mode, const std::string& config_path, const std::string& db_config) +game_boot_result Emulator::BootGame(const std::string& path, const std::string& title_id, bool direct, cfg_mode config_mode, const std::string& config_path, const std::optional& db_config) { if (m_restrict_emu_state_change) { @@ -1565,8 +1565,23 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, sys_log.notice("Version: APP_VER=%s VERSION=%s", version_app, version_disc); { - // We add the database configuration if it is set, unless we are using a mode that specifically selects a different configuration. - bool add_database_config = !m_db_config.empty() && (m_config_mode == cfg_mode::database_config || m_config_mode == cfg_mode::custom || m_config_mode == cfg_mode::continuous); + if (m_config_mode == cfg_mode::database_config || m_config_mode == cfg_mode::custom) + { + if (!m_db_config) + { + // Get database config if possible. This only happens if the database config hasn't been set by the UI (e.g. if booted with no-gui). + // We only know the title_id for sure at this point, so it doesn't make sense to retrieve it earlier. + m_db_config = Emu.GetCallbacks().get_database_config(m_title_id); + } + + // We add the database configuration if it is set, unless we are using a mode that specifically selects a different configuration. + m_add_database_config = m_db_config && !m_db_config->empty(); + } + else if (m_config_mode != cfg_mode::continuous) + { + // Reset flag unless in continuous mode + m_add_database_config = false; + } if (m_config_mode == cfg_mode::custom_selection || (m_config_mode == cfg_mode::continuous && !m_config_path.empty())) { @@ -1610,7 +1625,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, { g_cfg.name = config_path; m_config_path = config_path; - add_database_config = false; // A custom config exists. Do not add the database config. + m_add_database_config = false; // A custom config exists. Do not add the database config. break; } @@ -1619,12 +1634,12 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, } } - if (add_database_config) + if (m_add_database_config && m_db_config && !m_db_config->empty()) { // Add database config sys_log.notice("Applying database config"); - if (g_cfg.from_string(m_db_config)) + if (g_cfg.from_string(*m_db_config)) { g_cfg.name = "database_config"; } @@ -3373,7 +3388,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s klic.clear(); hdd1.clear(); init_mem_containers = nullptr; - m_db_config.clear(); + m_db_config = std::nullopt; m_config_path.clear(); m_config_mode = cfg_mode::custom; read_used_savestate_versions(); @@ -4018,7 +4033,9 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s if (allow_autoexit) { - Quit(g_cfg.misc.autoexit.get()); + const bool autoexit = g_cfg.misc.autoexit.get(); + sys_log.notice("Quit with main_window::closeEvent. (autoexit=%d)", autoexit); + Quit(autoexit); } if (after_kill_callback) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 08db927452..8bee2dc7a5 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -115,6 +115,7 @@ struct EmuCallbacks std::function check_microphone_permissions; std::function()> make_video_source; std::function enable_gamemode; + std::function get_database_config; }; namespace utils @@ -146,7 +147,7 @@ class Emulator final cfg_mode m_config_mode = cfg_mode::custom; std::string m_config_path; - std::string m_db_config; + std::optional m_db_config; // std::nullopt means it has not been retrieved yet std::string m_path; std::string m_path_old; std::string m_path_original; @@ -171,6 +172,7 @@ class Emulator final bool m_continuous_mode = false; bool m_has_gui = true; + bool m_add_database_config = false; bool m_state_inspection_savestate = false; @@ -370,7 +372,8 @@ public: const std::string& GetUsedDatabaseConfig() const { - return m_db_config; + static std::string empty_db_config; + return m_db_config ? *m_db_config : empty_db_config; } bool IsChildProcess() const @@ -422,7 +425,7 @@ public: return emulation_state_guard_t{this}; } - game_boot_result BootGame(const std::string& path, const std::string& title_id = "", bool direct = false, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::string& db_config = ""); + game_boot_result BootGame(const std::string& path, const std::string& title_id = "", bool direct = false, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::optional& db_config = std::nullopt); bool BootRsxCapture(const std::string& path); void SetForceBoot(bool force_boot); diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index befb64f282..f9f6f2c8d3 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -198,7 +198,7 @@ struct cfg_root : cfg::node { node_perf_overlay(cfg::node* _this) : cfg::node(_this, "Performance Overlay") {} - cfg::_bool perf_overlay_enabled{ this, "Enabled", false, true }; + cfg::_bool enabled{ this, "Enabled", false, true }; cfg::_bool framerate_graph_enabled{ this, "Enable Framerate Graph", false, true }; cfg::_bool frametime_graph_enabled{ this, "Enable Frametime Graph", false, true }; cfg::uint<2, 6000> framerate_datapoint_count{ this, "Framerate datapoints", 50, true }; @@ -219,7 +219,7 @@ struct cfg_root : cfg::node cfg::string background_body{ this, "Body Background (hex)", "#002339FF", true }; cfg::string color_title{ this, "Title Color (hex)", "#F26C24FF", true }; cfg::string background_title{ this, "Title Background (hex)", "#00000000", true }; - cfg::_bool perf_overlay_use_window_space{this, "Use Window Space", false, true}; + cfg::_bool use_window_space{this, "Use Window Space", false, true}; } perf_overlay{ this }; @@ -282,7 +282,7 @@ struct cfg_root : cfg::node cfg::_bool paint_move_spheres{this, "Paint move spheres", false, true}; cfg::_bool allow_move_hue_set_by_game{this, "Allow move hue set by game", false, true}; cfg::_bool lock_overlay_input_to_player_one{this, "Lock overlay input to player one", false, true}; - cfg::string midi_devices{this, "Emulated Midi devices", "ßßß@@@ßßß@@@ßßß@@@"}; + cfg::string midi_devices{this, "Emulated Midi devices", "Keyboardßßß@@@Keyboardßßß@@@Keyboardßßß@@@"}; cfg::_bool load_sdl_mappings{ this, "Load SDL GameController Mappings", true }; cfg::_bool pad_debug_overlay{ this, "IO Debug overlay", false, true }; cfg::_bool mouse_debug_overlay{ this, "Mouse Debug overlay", false, true }; diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index 8ec93ec8c7..0dd50501b6 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -199,7 +199,7 @@ bool iso_file_decryption::init(const std::string& path) const u32 region_count = char_arr_BE_to_uint(sec0_sec1.data()); // Ensure the region count is a proper value - if (region_count < 1 || region_count > 31) // It's non-PS3ISO + if (region_count < 1 || region_count > 127) // It's non-PS3ISO { iso_log.error("init: Failed to read region information: '%s' (region_count=%d)", path, region_count); return false; diff --git a/rpcs3/headless_application.cpp b/rpcs3/headless_application.cpp index 5d9240254d..cd8e027f57 100644 --- a/rpcs3/headless_application.cpp +++ b/rpcs3/headless_application.cpp @@ -58,7 +58,7 @@ void headless_application::InitializeCallbacks() on_exit(); } - sys_log.notice("Quitting headless application"); + sys_log.notice("Quitting headless application (force_quit=%d)", force_quit); quit(); return true; } diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index b5d4401b7e..8c067f3975 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -2,6 +2,8 @@ #include "main_application.h" #include "display_sleep_control.h" #include "gamemode_control.h" +#include "rpcs3qt/gui_settings.h" +#include "rpcs3qt/config_database.h" #include "util/types.hpp" #include "util/logs.hpp" @@ -409,5 +411,28 @@ EmuCallbacks main_application::CreateCallbacks() return path + suffix; }; + callbacks.get_database_config = [](const std::string& title_id) + { + if (title_id.empty()) + return std::string(); + + sys_log.notice("Trying to retrieve database config for: '%s'", title_id); + + const auto settings = std::make_shared(); + config_database config_db(settings, nullptr); + config_db.request_config_database(false); + + if (!config_db.has_config(title_id)) + return std::string(); + + if (const auto config = config_db.get_config(title_id)) + { + sys_log.notice("Found database config for: '%s'", title_id); + return config.value(); + } + + return std::string(); + }; + return callbacks; } diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 0181ce8c84..2ab3e592bc 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -837,6 +837,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 793e695d77..8c5b6b2905 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -1299,6 +1299,9 @@ Gui\utils + + Gui\settings + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index fdfb437fe7..0a63343e96 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(rpcs3_ui STATIC dimensions_dialog.cpp _discord_utils.cpp emu_settings.cpp + emu_settings_type.cpp elf_memory_dumping_dialog.cpp emulated_pad_settings_dialog.cpp emulated_logitech_g27_settings_dialog.cpp diff --git a/rpcs3/rpcs3qt/config_checker.cpp b/rpcs3/rpcs3qt/config_checker.cpp index 6a0851362a..f8ff600205 100644 --- a/rpcs3/rpcs3qt/config_checker.cpp +++ b/rpcs3/rpcs3qt/config_checker.cpp @@ -1,76 +1,127 @@ #include "stdafx.h" #include "config_checker.h" +#include "midi_creator.h" +#include "microphone_creator.h" #include "Emu/system_config.h" +#include "Emu/system_utils.hpp" +#include #include #include #include -#include #include -#include LOG_CHANNEL(gui_log, "GUI"); -config_checker::config_checker(QWidget* parent, const QString& content, bool is_log) : QDialog(parent) +config_checker::config_checker(QWidget* parent, const QString& content_or_serial, checker_mode mode, const std::string& db_config) + : QDialog(parent) + , m_checker_mode(mode) + , m_content_or_serial(content_or_serial) + , m_db_config(db_config) { setObjectName("config_checker"); + setWindowTitle(tr("Config Checker")); setAttribute(Qt::WA_DeleteOnClose); QVBoxLayout* layout = new QVBoxLayout(); - QLabel* label = new QLabel(this); - layout->addWidget(label); + QComboBox* combo = nullptr; - QString result; - - if (check_config(content, result, is_log)) + if (mode == checker_mode::gamelist) { - setWindowTitle(tr("Interesting!")); + m_serial = content_or_serial.toStdString(); - if (result.isEmpty()) + combo = new QComboBox(this); + + std::string custom_config_path; + if (std::string config_path = rpcs3::utils::get_custom_config_path(m_serial); fs::is_file(config_path)) { - label->setText(tr("Found config.\nIt seems to match the default config.")); + custom_config_path = std::move(config_path); + combo->addItem(tr("Custom Configuration"), static_cast(cfg_mode::custom)); } - else + + combo->addItem(tr("Database + Global Configuration"), static_cast(cfg_mode::database_config)); + combo->setCurrentIndex(combo->findData(static_cast(custom_config_path.empty() ? cfg_mode::database_config : cfg_mode::custom))); + + connect(combo, &QComboBox::currentIndexChanged, this, [this, combo]() { - label->setText(tr("Found config.\nSome settings seem to deviate from the default config:")); + check_config(static_cast(combo->currentData().toInt())); + }); - QTextEdit* text_box = new QTextEdit(); - text_box->setReadOnly(true); - text_box->setHtml(result); - layout->addWidget(text_box); + layout->addWidget(combo); + } - resize(400, 600); - } - } - else - { - setWindowTitle(tr("Ooops!")); - label->setText(result); - } + m_label = new QLabel(this); + layout->addWidget(m_label); + + m_text_box = new QTextEdit(); + m_text_box->setReadOnly(true); + layout->addWidget(m_text_box); QDialogButtonBox* box = new QDialogButtonBox(QDialogButtonBox::Close); connect(box, &QDialogButtonBox::rejected, this, &QDialog::reject); layout->addWidget(box); setLayout(layout); + resize(400, 600); + + check_config(combo ? static_cast(combo->currentData().toInt()) : cfg_mode::database_config); } -bool config_checker::check_config(QString content, QString& result, bool is_log) +void config_checker::check_config(cfg_mode mode) { - cfg_root config{}; + QString result; - if (is_log) + if (check_config(mode, m_content_or_serial, result)) + { + if (m_checker_mode == checker_mode::gamelist) + { + if (result.isEmpty()) + { + m_label->setText(tr("The configuration seems to match the default config.")); + } + else + { + m_label->setText(tr("Config database settings are marked with an * in front of the name.\nSome settings seem to deviate from the default config:")); + } + } + else + { + if (result.isEmpty()) + { + m_label->setText(tr("Found config.\nIt seems to match the default config.")); + } + else + { + m_label->setText(tr("Found config.\nSome settings seem to deviate from the default config:")); + } + } + + m_text_box->setVisible(!result.isEmpty()); + m_text_box->setHtml(result); + } + else + { + m_label->setText(result); + } +} + +bool config_checker::check_config(cfg_mode mode, QString content_or_serial, QString& result) +{ + std::unique_ptr config = std::make_unique(); + std::unique_ptr config_db_only; + + if (m_checker_mode == checker_mode::log) { const QString start_token = "SYS: Used configuration:\n"; const QString end_token = "\n·"; - qsizetype start = content.indexOf(start_token); + qsizetype start = content_or_serial.indexOf(start_token); qsizetype end = -1; if (start >= 0) { start += start_token.size(); - end = content.indexOf(end_token, start); + end = content_or_serial.indexOf(end_token, start); } if (end < 0) @@ -79,24 +130,93 @@ bool config_checker::check_config(QString content, QString& result, bool is_log) return false; } - content = content.mid(start, end - start); + content_or_serial = content_or_serial.mid(start, end - start); } - if (!config.from_string(content.toStdString())) + if (m_checker_mode == checker_mode::gamelist) { - gui_log.error("log_viewer: Failed to parse config:\n%s", content); + config->from_default(); + + // Load global config + const std::string cfg_path = fs::get_config_dir(true) + "config.yml"; + if (const fs::file cfg_file{cfg_path}) + { + gui_log.notice("config_checker: Applying global config: %s", cfg_path); + + if (!config->from_string(cfg_file.to_string())) + { + gui_log.error("config_checker: Failed to apply global config: %s", cfg_path); + result = tr("Failed to apply global config!"); + return false; + } + } + + // Load custom config + const std::string custom_config_path = rpcs3::utils::get_custom_config_path(m_serial); + if (mode == cfg_mode::custom && !custom_config_path.empty()) + { + if (const fs::file cfg_file{custom_config_path}) + { + gui_log.notice("config_checker: Applying custom config: %s", custom_config_path); + + if (!config->from_string(cfg_file.to_string())) + { + gui_log.error("config_checker: Failed to apply custom config: %s", custom_config_path); + result = tr("Failed to apply custom config!"); + return false; + } + } + } + + if (mode == cfg_mode::database_config && !m_db_config.empty()) + { + gui_log.notice("config_checker: Applying database config: %s", custom_config_path); + + if (!config->from_string(m_db_config)) + { + gui_log.error("config_checker: Failed to apply database config:\n%s", m_db_config); + result = tr("Failed to apply database config!"); + return false; + } + + config_db_only = std::make_unique(); + config_db_only->from_default(); + if (!config_db_only->from_string(m_db_config)) + { + gui_log.error("config_checker: Failed to apply database config:\n%s", m_db_config); + result = tr("Failed to apply database config!"); + return false; + } + } + } + else if (!config->from_string(content_or_serial.toStdString())) + { + gui_log.error("config_checker: Failed to parse config:\n%s", content_or_serial); result = tr("Cannot find any config!"); return false; } - std::function print_diff_recursive; - print_diff_recursive = [&print_diff_recursive](const cfg::_base* base, std::string& diff, int indentation) -> void + std::function print_diff_recursive; + print_diff_recursive = [this, &print_diff_recursive, &config](const cfg::_base* base, const cfg::_base* base_db_only, std::string& diff, int indentation) -> void { if (!base) { return; } + // Ignore some irrelevant settings in gamelist mode + if (m_checker_mode == checker_mode::gamelist && base->get_type() != cfg::type::node) + { + const std::string key = base->get_name(); + + if (key == config->sys.console_psid.get_name() || + key == config->sys.system_name.get_name() || + key == config->video.vk.adapter.get_name()) + { + return; + } + } + const auto indent = [](std::string& str, int indentation) { for (int i = 0; i < indentation * 2; i++) @@ -105,6 +225,16 @@ bool config_checker::check_config(QString content, QString& result, bool is_log) } }; + const auto base_name_db = [base](bool is_db_config) + { + if (is_db_config) + { + return "*" + base->get_name(); + } + + return base->get_name(); + }; + switch (base->get_type()) { case cfg::type::node: @@ -115,7 +245,20 @@ bool config_checker::check_config(QString content, QString& result, bool is_log) for (const auto& n : node->get_nodes()) { - print_diff_recursive(n, diff_tmp, indentation + 1); + const cfg::_base* n_db_only = nullptr; + if (const auto& node_db_only = static_cast(base_db_only)) + { + for (const auto& n_db : node_db_only->get_nodes()) + { + if (n_db->get_name() == n->get_name()) + { + n_db_only = n_db; + break; + } + } + } + + print_diff_recursive(n, n_db_only, diff_tmp, indentation + 1); } if (!diff_tmp.empty()) @@ -142,19 +285,75 @@ bool config_checker::check_config(QString content, QString& result, bool is_log) const std::string val = base->to_string(); const std::string def = base->def_to_string(); - if (val != def) - { - indent(diff, indentation); + if (val == def) + break; - if (def.empty()) + indent(diff, indentation); + + if (m_checker_mode == checker_mode::gamelist) + { + if (base->get_name() == config->io.midi_devices.get_name()) { - fmt::append(diff, "%s: %s
", base->get_name(), val); + fmt::append(diff, "%s:
", base->get_name()); + + midi_creator mc {}; + + mc.parse_devices(def); + const std::array def_devices = mc.get_selection_list(); + + mc.parse_devices(val); + const std::array devices = mc.get_selection_list(); + + for (usz i = 0; i < devices.size(); i++) + { + const midi_device& def_device = def_devices[i]; + const midi_device& device = devices[i]; + + if (device.name == def_device.name) + continue; + + indent(diff, indentation + 1); + fmt::append(diff, "Device %d: %s: %s
", i + 1, device.type, device.name); + } + break; } - else + else if (base->get_name() == config->audio.microphone_devices.get_name()) { - fmt::append(diff, "%s: %s default: %s
", base->get_name(), val, def); + fmt::append(diff, "%s:
", base->get_name()); + + microphone_creator mc {}; + + mc.parse_devices(def); + const std::array def_devices = mc.get_selection_list(); + + mc.parse_devices(val); + const std::array devices = mc.get_selection_list(); + + for (usz i = 0; i < devices.size(); i++) + { + const std::string& def_device = def_devices[i]; + const std::string& device = devices[i]; + + if (device == def_device) + continue; + + indent(diff, indentation + 1); + fmt::append(diff, "Device %d: %s
", i + 1, device); + } + break; } } + + const bool is_db_config = base_db_only && base_db_only->to_string() != def; + + if (def.empty()) + { + fmt::append(diff, "%s: %s
", base_name_db(is_db_config), val); + } + else + { + fmt::append(diff, "%s: %s default: %s
", base_name_db(is_db_config), val, def); + } break; } case cfg::type::set: @@ -208,7 +407,7 @@ bool config_checker::check_config(QString content, QString& result, bool is_log) }; std::string diff; - print_diff_recursive(&config, diff, 0); + print_diff_recursive(config.get(), config_db_only.get(), diff, 0); result = QString::fromStdString(diff); return true; diff --git a/rpcs3/rpcs3qt/config_checker.h b/rpcs3/rpcs3qt/config_checker.h index 900fb30351..71b4a27de3 100644 --- a/rpcs3/rpcs3qt/config_checker.h +++ b/rpcs3/rpcs3qt/config_checker.h @@ -1,13 +1,34 @@ #pragma once +#include "Emu/config_mode.h" + #include +#include +#include class config_checker : public QDialog { Q_OBJECT public: - config_checker(QWidget* parent, const QString& path, bool is_log); + enum class checker_mode + { + config, + log, + gamelist + }; - bool check_config(QString content, QString& result, bool is_log); + config_checker(QWidget* parent, const QString& content_or_serial, checker_mode mode, const std::string& db_config = {}); + +private: + void check_config(cfg_mode mode); + bool check_config(cfg_mode mode, QString content_or_serial, QString& result); + + QLabel* m_label = nullptr; + QTextEdit* m_text_box = nullptr; + + checker_mode m_checker_mode = checker_mode::config; + QString m_content_or_serial; + std::string m_db_config; + std::string m_serial; }; diff --git a/rpcs3/rpcs3qt/downloader.cpp b/rpcs3/rpcs3qt/downloader.cpp index 9a5038fcc1..9bcdbf495a 100644 --- a/rpcs3/rpcs3qt/downloader.cpp +++ b/rpcs3/rpcs3qt/downloader.cpp @@ -103,7 +103,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p { if (m_curl_abort) { - network_log.notice("Download aborted"); + network_log.notice("Download aborted (url='%s')", url); return; } @@ -114,7 +114,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p if (m_curl_success) { - network_log.notice("Download finished"); + network_log.notice("Download finished (url='%s')", url); if (check_return_code && m_download_attempts < 3) { diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index a5bd055432..38fd5d2a94 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -1531,7 +1531,7 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_ std::string type_string; if (const auto it = settings_location.find(type); it != settings_location.cend()) { - for (const char* loc : it->second) + for (const std::string& loc : it->second) { if (!type_string.empty()) type_string += ": "; type_string += loc; diff --git a/rpcs3/rpcs3qt/emu_settings_type.cpp b/rpcs3/rpcs3qt/emu_settings_type.cpp new file mode 100644 index 0000000000..4b032c78c5 --- /dev/null +++ b/rpcs3/rpcs3qt/emu_settings_type.cpp @@ -0,0 +1,240 @@ +#include "stdafx.h" +#include "emu_settings_type.h" +#include "Emu/system_config.h" + +const cfg_root local_cfg {}; // Local config to ensure we have an initialized object + +cfg_location get_cfg_location(const cfg::_base& leaf) +{ + cfg_location loc {}; + loc.push_back(leaf.get_name()); + + for (const cfg::_base* node = leaf.get_parent(); node && !node->get_name().empty(); node = node->get_parent()) + { + loc.push_front(node->get_name()); + } + + return loc; +} + +const std::map settings_location = +{ + // Core Tab + { emu_settings_type::PPUDecoder, get_cfg_location(local_cfg.core.ppu_decoder) }, + { emu_settings_type::SPUDecoder, get_cfg_location(local_cfg.core.spu_decoder) }, + { emu_settings_type::HookStaticFuncs, get_cfg_location(local_cfg.core.hook_functions) }, + { emu_settings_type::ThreadSchedulerMode, get_cfg_location(local_cfg.core.thread_scheduler) }, + { emu_settings_type::SPULoopDetection, get_cfg_location(local_cfg.core.spu_loop_detection) }, + { emu_settings_type::PreferredSPUThreads, get_cfg_location(local_cfg.core.preferred_spu_threads) }, + { emu_settings_type::PPUDebug, get_cfg_location(local_cfg.core.ppu_debug) }, + { emu_settings_type::SPUDebug, get_cfg_location(local_cfg.core.spu_debug) }, + { emu_settings_type::MFCDebug, get_cfg_location(local_cfg.core.mfc_debug) }, + { emu_settings_type::MaxLLVMThreads, get_cfg_location(local_cfg.core.llvm_threads) }, + { emu_settings_type::LLVMPrecompilation, get_cfg_location(local_cfg.core.llvm_precompilation) }, + { emu_settings_type::AccurateSpuDMA, get_cfg_location(local_cfg.core.spu_accurate_dma) }, + { emu_settings_type::AccurateClineStores, get_cfg_location(local_cfg.core.accurate_cache_line_stores) }, + { emu_settings_type::AccurateRSXAccess, get_cfg_location(local_cfg.core.rsx_accurate_res_access) }, + { emu_settings_type::FIFOAccuracy, get_cfg_location(local_cfg.core.rsx_fifo_accuracy) }, + { emu_settings_type::XFloatAccuracy, get_cfg_location(local_cfg.core.spu_xfloat_accuracy) }, + { emu_settings_type::MFCCommandsShuffling, get_cfg_location(local_cfg.core.mfc_transfers_shuffling) }, + { emu_settings_type::SetDAZandFTZ, get_cfg_location(local_cfg.core.set_daz_and_ftz) }, + { emu_settings_type::SPUBlockSize, get_cfg_location(local_cfg.core.spu_block_size) }, + { emu_settings_type::SPUCache, get_cfg_location(local_cfg.core.spu_cache) }, + { emu_settings_type::DebugConsoleMode, get_cfg_location(local_cfg.core.debug_console_mode) }, + { emu_settings_type::MaxSPURSThreads, get_cfg_location(local_cfg.core.max_spurs_threads) }, + { emu_settings_type::SleepTimersAccuracy, get_cfg_location(local_cfg.core.sleep_timers_accuracy) }, + { emu_settings_type::ClocksScale, get_cfg_location(local_cfg.core.clocks_scale) }, + { emu_settings_type::AccuratePPU128Loop, get_cfg_location(local_cfg.core.ppu_128_reservations_loop_max_length) }, + { emu_settings_type::PerformanceReport, get_cfg_location(local_cfg.core.perf_report) }, + { emu_settings_type::NumPPUThreads, get_cfg_location(local_cfg.core.ppu_threads) }, + { emu_settings_type::PPUNJFixup, get_cfg_location(local_cfg.core.ppu_llvm_nj_fixup) }, + { emu_settings_type::PPUVNANFixup, get_cfg_location(local_cfg.core.ppu_fix_vnan) }, + { emu_settings_type::AccurateDFMA, get_cfg_location(local_cfg.core.use_accurate_dfma) }, + { emu_settings_type::AccuratePPUSAT, get_cfg_location(local_cfg.core.ppu_set_sat_bit) }, + { emu_settings_type::AccuratePPUNJ, get_cfg_location(local_cfg.core.ppu_use_nj_bit) }, + { emu_settings_type::AccuratePPUVNAN, get_cfg_location(local_cfg.core.ppu_set_vnan) }, + { emu_settings_type::AccuratePPUFPCC, get_cfg_location(local_cfg.core.ppu_set_fpcc) }, + { emu_settings_type::MaxPreemptCount, get_cfg_location(local_cfg.core.max_cpu_preempt_count_per_frame) }, + { emu_settings_type::SPUProfiler, get_cfg_location(local_cfg.core.spu_prof) }, + { emu_settings_type::DisableSpinOptimization, get_cfg_location(local_cfg.core.spu_getllar_spin_optimization_disabled) }, + { emu_settings_type::EnabledSPUEventsBusyLoop, get_cfg_location(local_cfg.core.spu_reservation_busy_waiting_enabled) }, + + // Graphics Tab + { emu_settings_type::Renderer, get_cfg_location(local_cfg.video.renderer) }, + { emu_settings_type::Resolution, get_cfg_location(local_cfg.video.resolution) }, + { emu_settings_type::AspectRatio, get_cfg_location(local_cfg.video.aspect_ratio) }, + { emu_settings_type::FrameLimit, get_cfg_location(local_cfg.video.frame_limit) }, + { emu_settings_type::MSAA, get_cfg_location(local_cfg.video.antialiasing_level) }, + { emu_settings_type::LogShaderPrograms, get_cfg_location(local_cfg.video.log_programs) }, + { emu_settings_type::WriteDepthBuffer, get_cfg_location(local_cfg.video.write_depth_buffer) }, + { emu_settings_type::WriteColorBuffers, get_cfg_location(local_cfg.video.write_color_buffers) }, + { emu_settings_type::ReadColorBuffers, get_cfg_location(local_cfg.video.read_color_buffers) }, + { emu_settings_type::ReadDepthBuffer, get_cfg_location(local_cfg.video.read_depth_buffer) }, + { emu_settings_type::HandleRSXTiledMemory, get_cfg_location(local_cfg.video.handle_tiled_memory) }, + { emu_settings_type::VSync, get_cfg_location(local_cfg.video.vsync) }, + { emu_settings_type::DebugOutput, get_cfg_location(local_cfg.video.debug_output) }, + { emu_settings_type::DebugOverlay, get_cfg_location(local_cfg.video.debug_overlay) }, + { emu_settings_type::RenderdocCompatibility, get_cfg_location(local_cfg.video.renderdoc_compatiblity) }, + { emu_settings_type::GPUTextureScaling, get_cfg_location(local_cfg.video.use_gpu_texture_scaling) }, + { emu_settings_type::StretchToDisplayArea, get_cfg_location(local_cfg.video.stretch_to_display_area) }, + { emu_settings_type::ForceHighpZ, get_cfg_location(local_cfg.video.force_high_precision_z_buffer) }, + { emu_settings_type::StrictRenderingMode, get_cfg_location(local_cfg.video.strict_rendering_mode) }, + { emu_settings_type::DisableVertexCache, get_cfg_location(local_cfg.video.disable_vertex_cache) }, + { emu_settings_type::DisableOcclusionQueries, get_cfg_location(local_cfg.video.disable_zcull_queries) }, + { emu_settings_type::DisableVideoOutput, get_cfg_location(local_cfg.video.disable_video_output) }, + { emu_settings_type::DisableFIFOReordering, get_cfg_location(local_cfg.video.disable_FIFO_reordering) }, + { emu_settings_type::StereoRenderEnabled, get_cfg_location(local_cfg.video.stereo_enabled) }, + { emu_settings_type::StereoRenderMode, get_cfg_location(local_cfg.video.stereo_render_mode) }, + { emu_settings_type::ScreenSize, get_cfg_location(local_cfg.video.screen_size) }, + { emu_settings_type::StrictTextureFlushing, get_cfg_location(local_cfg.video.strict_texture_flushing) }, + { emu_settings_type::ForceCPUBlitEmulation, get_cfg_location(local_cfg.video.force_cpu_blit_processing) }, + { emu_settings_type::DisableOnDiskShaderCache, get_cfg_location(local_cfg.video.disable_on_disk_shader_cache) }, + { emu_settings_type::DisableVulkanMemAllocator, get_cfg_location(local_cfg.video.disable_vulkan_mem_allocator) }, + { emu_settings_type::ShaderMode, get_cfg_location(local_cfg.video.shadermode) }, + { emu_settings_type::ShaderCompilerNumThreads, get_cfg_location(local_cfg.video.shader_compiler_threads_count) }, + { emu_settings_type::ShaderPrecisionQuality, get_cfg_location(local_cfg.video.shader_precision) }, + { emu_settings_type::MultithreadedRSX, get_cfg_location(local_cfg.video.multithreaded_rsx) }, + { emu_settings_type::RelaxedZCULL, get_cfg_location(local_cfg.video.relaxed_zcull_sync) }, + { emu_settings_type::PreciseZCULL, get_cfg_location(local_cfg.video.precise_zpass_count) }, + { emu_settings_type::AnisotropicFilterOverride, get_cfg_location(local_cfg.video.anisotropic_level_override) }, + { emu_settings_type::TextureLodBias, get_cfg_location(local_cfg.video.texture_lod_bias) }, + { emu_settings_type::ResolutionScale, get_cfg_location(local_cfg.video.resolution_scale_percent) }, + { emu_settings_type::MinimumScalableDimension, get_cfg_location(local_cfg.video.min_scalable_dimension) }, + { emu_settings_type::VBlankRate, get_cfg_location(local_cfg.video.vblank_rate) }, + { emu_settings_type::VBlankNTSCFixup, get_cfg_location(local_cfg.video.vblank_ntsc) }, + { emu_settings_type::DriverWakeUpDelay, get_cfg_location(local_cfg.video.driver_wakeup_delay) }, + { emu_settings_type::AllowHostGPULabels, get_cfg_location(local_cfg.video.host_label_synchronization) }, + { emu_settings_type::DisableMSLFastMath, get_cfg_location(local_cfg.video.disable_msl_fast_math) }, + { emu_settings_type::OutputScalingMode, get_cfg_location(local_cfg.video.output_scaling) }, + { emu_settings_type::ForceHwMSAAResolve, get_cfg_location(local_cfg.video.force_hw_MSAA_resolve) }, + { emu_settings_type::DisableAsyncHostMM, get_cfg_location(local_cfg.video.disable_async_host_memory_manager) }, + { emu_settings_type::RecordWithOverlays, get_cfg_location(local_cfg.video.record_with_overlays) }, + { emu_settings_type::DisableHWTexelRemapping, get_cfg_location(local_cfg.video.disable_hardware_texel_remapping) }, + { emu_settings_type::FsrSharpeningStrength, get_cfg_location(local_cfg.video.rcas_sharpening_intensity) }, + + // Vulkan + { emu_settings_type::VulkanAdapter, get_cfg_location(local_cfg.video.vk.adapter) }, + { emu_settings_type::VulkanAsyncTextureUploads, get_cfg_location(local_cfg.video.vk.asynchronous_texture_streaming) }, + { emu_settings_type::VulkanAsyncSchedulerDriver, get_cfg_location(local_cfg.video.vk.asynchronous_scheduler) }, + { emu_settings_type::ExclusiveFullscreenMode, get_cfg_location(local_cfg.video.vk.exclusive_fullscreen_mode) }, + { emu_settings_type::UseReBAR, get_cfg_location(local_cfg.video.vk.use_rebar_upload_heap) }, + + // Performance Overlay + { emu_settings_type::PerfOverlayEnabled, get_cfg_location(local_cfg.video.perf_overlay.enabled) }, + { emu_settings_type::PerfOverlayFramerateGraphEnabled, get_cfg_location(local_cfg.video.perf_overlay.framerate_graph_enabled) }, + { emu_settings_type::PerfOverlayFrametimeGraphEnabled, get_cfg_location(local_cfg.video.perf_overlay.frametime_graph_enabled) }, + { emu_settings_type::PerfOverlayFramerateDatapoints, get_cfg_location(local_cfg.video.perf_overlay.framerate_datapoint_count) }, + { emu_settings_type::PerfOverlayFrametimeDatapoints, get_cfg_location(local_cfg.video.perf_overlay.frametime_datapoint_count) }, + { emu_settings_type::PerfOverlayDetailLevel, get_cfg_location(local_cfg.video.perf_overlay.level) }, + { emu_settings_type::PerfOverlayFramerateDetailLevel, get_cfg_location(local_cfg.video.perf_overlay.framerate_graph_detail_level) }, + { emu_settings_type::PerfOverlayFrametimeDetailLevel, get_cfg_location(local_cfg.video.perf_overlay.frametime_graph_detail_level) }, + { emu_settings_type::PerfOverlayPosition, get_cfg_location(local_cfg.video.perf_overlay.position) }, + { emu_settings_type::PerfOverlayUpdateInterval, get_cfg_location(local_cfg.video.perf_overlay.update_interval) }, + { emu_settings_type::PerfOverlayFontSize, get_cfg_location(local_cfg.video.perf_overlay.font_size) }, + { emu_settings_type::PerfOverlayOpacity, get_cfg_location(local_cfg.video.perf_overlay.opacity) }, + { emu_settings_type::PerfOverlayMarginX, get_cfg_location(local_cfg.video.perf_overlay.margin_x) }, + { emu_settings_type::PerfOverlayMarginY, get_cfg_location(local_cfg.video.perf_overlay.margin_y) }, + { emu_settings_type::PerfOverlayCenterX, get_cfg_location(local_cfg.video.perf_overlay.center_x) }, + { emu_settings_type::PerfOverlayCenterY, get_cfg_location(local_cfg.video.perf_overlay.center_y) }, + { emu_settings_type::PerfOverlayUseWindowSpace, get_cfg_location(local_cfg.video.perf_overlay.use_window_space) }, + + // Shader Loading Dialog + { emu_settings_type::ShaderLoadBgEnabled, get_cfg_location(local_cfg.video.shader_preloading_dialog.use_custom_background) }, + { emu_settings_type::ShaderLoadBgDarkening, get_cfg_location(local_cfg.video.shader_preloading_dialog.darkening_strength) }, + { emu_settings_type::ShaderLoadBgBlur, get_cfg_location(local_cfg.video.shader_preloading_dialog.blur_strength) }, + + // Audio + { emu_settings_type::AudioRenderer, get_cfg_location(local_cfg.audio.renderer) }, + { emu_settings_type::DumpToFile, get_cfg_location(local_cfg.audio.dump_to_file) }, + { emu_settings_type::ConvertTo16Bit, get_cfg_location(local_cfg.audio.convert_to_s16) }, + { emu_settings_type::AudioFormat, get_cfg_location(local_cfg.audio.format) }, + { emu_settings_type::AudioFormats, get_cfg_location(local_cfg.audio.formats) }, + { emu_settings_type::AudioProvider, get_cfg_location(local_cfg.audio.provider) }, + { emu_settings_type::AudioAvport, get_cfg_location(local_cfg.audio.rsxaudio_port) }, + { emu_settings_type::AudioDevice, get_cfg_location(local_cfg.audio.audio_device) }, + { emu_settings_type::AudioChannelLayout, get_cfg_location(local_cfg.audio.channel_layout) }, + { emu_settings_type::MasterVolume, get_cfg_location(local_cfg.audio.volume) }, + { emu_settings_type::EnableBuffering, get_cfg_location(local_cfg.audio.enable_buffering) }, + { emu_settings_type::AudioBufferDuration, get_cfg_location(local_cfg.audio.desired_buffer_duration) }, + { emu_settings_type::EnableTimeStretching, get_cfg_location(local_cfg.audio.enable_time_stretching) }, + { emu_settings_type::TimeStretchingThreshold, get_cfg_location(local_cfg.audio.time_stretching_threshold) }, + { emu_settings_type::MicrophoneType, get_cfg_location(local_cfg.audio.microphone_type) }, + { emu_settings_type::MicrophoneDevices, get_cfg_location(local_cfg.audio.microphone_devices) }, + { emu_settings_type::MusicHandler, get_cfg_location(local_cfg.audio.music) }, + + // Input / Output + { emu_settings_type::BackgroundInput, get_cfg_location(local_cfg.io.background_input_enabled) }, + { emu_settings_type::ShowMoveCursor, get_cfg_location(local_cfg.io.show_move_cursor) }, + { emu_settings_type::LockOvlIptToP1, get_cfg_location(local_cfg.io.lock_overlay_input_to_player_one) }, + { emu_settings_type::PadHandlerMode, get_cfg_location(local_cfg.io.pad_mode) }, + { emu_settings_type::PadConnection, get_cfg_location(local_cfg.io.keep_pads_connected) }, + { emu_settings_type::KeyboardHandler, get_cfg_location(local_cfg.io.keyboard) }, + { emu_settings_type::MouseHandler, get_cfg_location(local_cfg.io.mouse) }, + { emu_settings_type::Camera, get_cfg_location(local_cfg.io.camera) }, + { emu_settings_type::CameraType, get_cfg_location(local_cfg.io.camera_type) }, + { emu_settings_type::CameraFlip, get_cfg_location(local_cfg.io.camera_flip_option) }, + { emu_settings_type::CameraID, get_cfg_location(local_cfg.io.camera_id) }, + { emu_settings_type::Move, get_cfg_location(local_cfg.io.move) }, + { emu_settings_type::Buzz, get_cfg_location(local_cfg.io.buzz) }, + { emu_settings_type::Turntable, get_cfg_location(local_cfg.io.turntable) }, + { emu_settings_type::GHLtar, get_cfg_location(local_cfg.io.ghltar) }, + { emu_settings_type::MidiDevices, get_cfg_location(local_cfg.io.midi_devices) }, + { emu_settings_type::SDLMappings, get_cfg_location(local_cfg.io.load_sdl_mappings) }, + { emu_settings_type::IoDebugOverlay, get_cfg_location(local_cfg.io.pad_debug_overlay) }, + { emu_settings_type::MouseDebugOverlay, get_cfg_location(local_cfg.io.mouse_debug_overlay) }, + + // Misc + { emu_settings_type::ExitRPCS3OnFinish, get_cfg_location(local_cfg.misc.autoexit) }, + { emu_settings_type::StartOnBoot, get_cfg_location(local_cfg.misc.autostart) }, + { emu_settings_type::PauseOnFocusLoss, get_cfg_location(local_cfg.misc.autopause) }, + { emu_settings_type::StartGameFullscreen, get_cfg_location(local_cfg.misc.start_fullscreen) }, + { emu_settings_type::PreventDisplaySleep, get_cfg_location(local_cfg.misc.prevent_display_sleep) }, + { emu_settings_type::ShowTrophyPopups, get_cfg_location(local_cfg.misc.show_trophy_popups) }, + { emu_settings_type::ShowRpcnPopups, get_cfg_location(local_cfg.misc.show_rpcn_popups) }, + { emu_settings_type::UseNativeInterface, get_cfg_location(local_cfg.misc.use_native_interface) }, + { emu_settings_type::ShowShaderCompilationHint, get_cfg_location(local_cfg.misc.show_shader_compilation_hint) }, + { emu_settings_type::ShowPPUCompilationHint, get_cfg_location(local_cfg.misc.show_ppu_compilation_hint) }, + { emu_settings_type::ShowAutosaveAutoloadHint, get_cfg_location(local_cfg.misc.show_autosave_autoload_hint) }, + { emu_settings_type::ShowPressureIntensityToggleHint, get_cfg_location(local_cfg.misc.show_pressure_intensity_toggle_hint) }, + { emu_settings_type::ShowAnalogLimiterToggleHint, get_cfg_location(local_cfg.misc.show_analog_limiter_toggle_hint) }, + { emu_settings_type::ShowMouseAndKeyboardToggleHint, get_cfg_location(local_cfg.misc.show_mouse_and_keyboard_toggle_hint) }, + { emu_settings_type::ShowFatalErrorHints, get_cfg_location(local_cfg.misc.show_fatal_error_hints) }, + { emu_settings_type::ShowCaptureHints, get_cfg_location(local_cfg.misc.show_capture_hints) }, + { emu_settings_type::SilenceAllLogs, get_cfg_location(local_cfg.misc.silence_all_logs) }, + { emu_settings_type::WindowTitleFormat, get_cfg_location(local_cfg.misc.title_format) }, + { emu_settings_type::PauseDuringHomeMenu, get_cfg_location(local_cfg.misc.pause_during_home_menu) }, + { emu_settings_type::PlayMusicDuringBoot, get_cfg_location(local_cfg.misc.play_music_during_boot) }, + { emu_settings_type::EnableGamemode, get_cfg_location(local_cfg.misc.enable_gamemode) }, + + // Networking + { emu_settings_type::InternetStatus, get_cfg_location(local_cfg.net.net_active) }, + { emu_settings_type::DNSAddress, get_cfg_location(local_cfg.net.dns) }, + { emu_settings_type::IpSwapList, get_cfg_location(local_cfg.net.swap_list) }, + { emu_settings_type::PSNStatus, get_cfg_location(local_cfg.net.psn_status) }, + { emu_settings_type::BindAddress, get_cfg_location(local_cfg.net.bind_address) }, + { emu_settings_type::EnableUpnp, get_cfg_location(local_cfg.net.upnp_enabled) }, + { emu_settings_type::PSNCountry, get_cfg_location(local_cfg.net.country) }, + { emu_settings_type::EnableClans, get_cfg_location(local_cfg.net.clans_enabled) }, + + // System + { emu_settings_type::LicenseArea, get_cfg_location(local_cfg.sys.license_area) }, + { emu_settings_type::Language, get_cfg_location(local_cfg.sys.language) }, + { emu_settings_type::KeyboardType, get_cfg_location(local_cfg.sys.keyboard_type) }, + { emu_settings_type::EnterButtonAssignment, get_cfg_location(local_cfg.sys.enter_button_assignment) }, + { emu_settings_type::DateFormat, get_cfg_location(local_cfg.sys.date_fmt) }, + { emu_settings_type::TimeFormat, get_cfg_location(local_cfg.sys.time_fmt) }, + { emu_settings_type::ConsoleTimeOffset, get_cfg_location(local_cfg.sys.console_time_offset) }, + + { emu_settings_type::EnableHostRoot, get_cfg_location(local_cfg.vfs.host_root) }, + { emu_settings_type::EmptyHdd0Tmp, get_cfg_location(local_cfg.vfs.empty_hdd0_tmp) }, + { emu_settings_type::LimitCacheSize, get_cfg_location(local_cfg.vfs.limit_cache_size) }, + { emu_settings_type::MaximumCacheSize, get_cfg_location(local_cfg.vfs.cache_max_size) }, + + // Savestates + { emu_settings_type::SuspendEmulationSavestateMode, get_cfg_location(local_cfg.savestate.suspend_emu) }, + { emu_settings_type::CompatibleEmulationSavestateMode, get_cfg_location(local_cfg.savestate.compatible_mode) }, + { emu_settings_type::StartSavestatePaused, get_cfg_location(local_cfg.savestate.start_paused) }, + + // Logs + { emu_settings_type::Log, get_cfg_location(local_cfg.log)}, +}; diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 4824719769..de04b81e85 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -1,10 +1,11 @@ #pragma once +#include #include -#include +#include // Node location -using cfg_location = std::vector; +using cfg_location = std::deque; enum class emu_settings_type { @@ -40,7 +41,6 @@ enum class emu_settings_type SleepTimersAccuracy, ClocksScale, PerformanceReport, - FullWidthAVX512, PPUNJFixup, PPUVNANFixup, AccurateDFMA, @@ -227,225 +227,4 @@ enum class emu_settings_type }; /** A helper map that keeps track of where a given setting type is located*/ -inline static const std::map settings_location = -{ - // Core Tab - { emu_settings_type::PPUDecoder, { "Core", "PPU Decoder"}}, - { emu_settings_type::SPUDecoder, { "Core", "SPU Decoder"}}, - { emu_settings_type::HookStaticFuncs, { "Core", "Hook static functions"}}, - { emu_settings_type::ThreadSchedulerMode, { "Core", "Thread Scheduler Mode"}}, - { emu_settings_type::SPULoopDetection, { "Core", "SPU loop detection"}}, - { emu_settings_type::PreferredSPUThreads, { "Core", "Preferred SPU Threads"}}, - { emu_settings_type::PPUDebug, { "Core", "PPU Debug"}}, - { emu_settings_type::SPUDebug, { "Core", "SPU Debug"}}, - { emu_settings_type::MFCDebug, { "Core", "MFC Debug"}}, - { emu_settings_type::MaxLLVMThreads, { "Core", "Max LLVM Compile Threads"}}, - { emu_settings_type::LLVMPrecompilation, { "Core", "LLVM Precompilation"}}, - { emu_settings_type::AccurateSpuDMA, { "Core", "Accurate SPU DMA"}}, - { emu_settings_type::AccurateClineStores, { "Core", "Accurate Cache Line Stores"}}, - { emu_settings_type::AccurateRSXAccess, { "Core", "Accurate RSX reservation access"}}, - { emu_settings_type::FIFOAccuracy, { "Core", "RSX FIFO Fetch Accuracy"}}, - { emu_settings_type::XFloatAccuracy, { "Core", "SPU XFloat Accuracy"}}, - { emu_settings_type::MFCCommandsShuffling, { "Core", "MFC Commands Shuffling Limit"}}, - { emu_settings_type::SetDAZandFTZ, { "Core", "Set DAZ and FTZ"}}, - { emu_settings_type::SPUBlockSize, { "Core", "SPU Block Size"}}, - { emu_settings_type::SPUCache, { "Core", "SPU Cache"}}, - { emu_settings_type::DebugConsoleMode, { "Core", "Debug Console Mode"}}, - { emu_settings_type::MaxSPURSThreads, { "Core", "Max SPURS Threads"}}, - { emu_settings_type::SleepTimersAccuracy, { "Core", "Sleep Timers Accuracy"}}, - { emu_settings_type::ClocksScale, { "Core", "Clocks scale"}}, - { emu_settings_type::AccuratePPU128Loop, { "Core", "Accurate PPU 128-byte Reservation Op Max Length"}}, - { emu_settings_type::PerformanceReport, { "Core", "Enable Performance Report"}}, - { emu_settings_type::FullWidthAVX512, { "Core", "Full Width AVX-512"}}, - { emu_settings_type::NumPPUThreads, { "Core", "PPU Threads"}}, - { emu_settings_type::PPUNJFixup, { "Core", "PPU LLVM Java Mode Handling"}}, - { emu_settings_type::PPUVNANFixup, { "Core", "PPU Vector NaN Handling"}}, - { emu_settings_type::AccurateDFMA, { "Core", "Use Accurate DFMA"}}, - { emu_settings_type::AccuratePPUSAT, { "Core", "PPU Set Saturation Bit"}}, - { emu_settings_type::AccuratePPUNJ, { "Core", "PPU Accurate Non-Java Mode"}}, - { emu_settings_type::AccuratePPUVNAN, { "Core", "PPU Accurate Vector NaN Values"}}, - { emu_settings_type::AccuratePPUFPCC, { "Core", "PPU Set FPCC Bits"}}, - { emu_settings_type::MaxPreemptCount, { "Core", "Max CPU Preempt Count"}}, - { emu_settings_type::SPUProfiler, { "Core", "SPU Profiler"}}, - { emu_settings_type::DisableSpinOptimization, { "Core", "Disable SPU GETLLAR Spin Optimization"}}, - { emu_settings_type::EnabledSPUEventsBusyLoop, { "Core", "SPU Reservation Busy Waiting Enabled"}}, - - // Graphics Tab - { emu_settings_type::Renderer, { "Video", "Renderer"}}, - { emu_settings_type::Resolution, { "Video", "Resolution"}}, - { emu_settings_type::AspectRatio, { "Video", "Aspect ratio"}}, - { emu_settings_type::FrameLimit, { "Video", "Frame limit"}}, - { emu_settings_type::MSAA, { "Video", "MSAA"}}, - { emu_settings_type::LogShaderPrograms, { "Video", "Log shader programs"}}, - { emu_settings_type::WriteDepthBuffer, { "Video", "Write Depth Buffer"}}, - { emu_settings_type::WriteColorBuffers, { "Video", "Write Color Buffers"}}, - { emu_settings_type::ReadColorBuffers, { "Video", "Read Color Buffers"}}, - { emu_settings_type::ReadDepthBuffer, { "Video", "Read Depth Buffer"}}, - { emu_settings_type::HandleRSXTiledMemory, { "Video", "Handle RSX Memory Tiling"}}, - { emu_settings_type::VSync, { "Video", "VSync Mode"}}, - { emu_settings_type::DebugOutput, { "Video", "Debug output"}}, - { emu_settings_type::DebugOverlay, { "Video", "Debug overlay"}}, - { emu_settings_type::RenderdocCompatibility, { "Video", "Renderdoc Compatibility Mode"}}, - { emu_settings_type::GPUTextureScaling, { "Video", "Use GPU texture scaling"}}, - { emu_settings_type::StretchToDisplayArea, { "Video", "Stretch To Display Area"}}, - { emu_settings_type::ForceHighpZ, { "Video", "Force High Precision Z buffer"}}, - { emu_settings_type::StrictRenderingMode, { "Video", "Strict Rendering Mode"}}, - { emu_settings_type::DisableVertexCache, { "Video", "Disable Vertex Cache"}}, - { emu_settings_type::DisableOcclusionQueries, { "Video", "Disable ZCull Occlusion Queries"}}, - { emu_settings_type::DisableVideoOutput, { "Video", "Disable Video Output"}}, - { emu_settings_type::DisableFIFOReordering, { "Video", "Disable FIFO Reordering"}}, - { emu_settings_type::StereoRenderEnabled, { "Video", "3D Display Enabled"}}, - { emu_settings_type::StereoRenderMode, { "Video", "3D Display Mode"}}, - { emu_settings_type::ScreenSize, { "Video", "Screen size in inches"}}, - { emu_settings_type::StrictTextureFlushing, { "Video", "Strict Texture Flushing"}}, - { emu_settings_type::ForceCPUBlitEmulation, { "Video", "Force CPU Blit"}}, - { emu_settings_type::DisableOnDiskShaderCache, { "Video", "Disable On-Disk Shader Cache"}}, - { emu_settings_type::DisableVulkanMemAllocator, { "Video", "Disable Vulkan Memory Allocator"}}, - { emu_settings_type::ShaderMode, { "Video", "Shader Mode"}}, - { emu_settings_type::ShaderCompilerNumThreads, { "Video", "Shader Compiler Threads"}}, - { emu_settings_type::ShaderPrecisionQuality, { "Video", "Shader Precision"}}, - { emu_settings_type::MultithreadedRSX, { "Video", "Multithreaded RSX"}}, - { emu_settings_type::RelaxedZCULL, { "Video", "Relaxed ZCULL Sync"}}, - { emu_settings_type::PreciseZCULL, { "Video", "Accurate ZCULL stats"}}, - { emu_settings_type::AnisotropicFilterOverride, { "Video", "Anisotropic Filter Override"}}, - { emu_settings_type::TextureLodBias, { "Video", "Texture LOD Bias Addend"}}, - { emu_settings_type::ResolutionScale, { "Video", "Resolution Scale"}}, - { emu_settings_type::MinimumScalableDimension, { "Video", "Minimum Scalable Dimension"}}, - { emu_settings_type::VulkanAdapter, { "Video", "Vulkan", "Adapter"}}, - { emu_settings_type::VBlankRate, { "Video", "Vblank Rate"}}, - { emu_settings_type::VBlankNTSCFixup, { "Video", "Vblank NTSC Fixup"}}, - { emu_settings_type::DriverWakeUpDelay, { "Video", "Driver Wake-Up Delay"}}, - { emu_settings_type::AllowHostGPULabels, { "Video", "Allow Host GPU Labels"}}, - { emu_settings_type::DisableMSLFastMath, { "Video", "Disable MSL Fast Math"}}, - { emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}}, - { emu_settings_type::ForceHwMSAAResolve, { "Video", "Force Hardware MSAA Resolve"}}, - { emu_settings_type::DisableAsyncHostMM, { "Video", "Disable Asynchronous Memory Manager"}}, - { emu_settings_type::RecordWithOverlays, { "Video", "Record With Overlays"}}, - { emu_settings_type::DisableHWTexelRemapping, { "Video", "Disable Hardware ColorSpace Remapping"}}, - { emu_settings_type::FsrSharpeningStrength, { "Video", "FidelityFX CAS Sharpening Intensity"}}, - - // Vulkan - { emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming"}}, - { emu_settings_type::VulkanAsyncSchedulerDriver, { "Video", "Vulkan", "Asynchronous Queue Scheduler"}}, - { emu_settings_type::ExclusiveFullscreenMode, { "Video", "Vulkan", "Exclusive Fullscreen Mode"}}, - { emu_settings_type::UseReBAR, { "Video", "Vulkan", "Use Re-BAR for GPU uploads"}}, - - // Performance Overlay - { emu_settings_type::PerfOverlayEnabled, { "Video", "Performance Overlay", "Enabled" } }, - { emu_settings_type::PerfOverlayFramerateGraphEnabled, { "Video", "Performance Overlay", "Enable Framerate Graph" } }, - { emu_settings_type::PerfOverlayFrametimeGraphEnabled, { "Video", "Performance Overlay", "Enable Frametime Graph" } }, - { emu_settings_type::PerfOverlayFramerateDatapoints, { "Video", "Performance Overlay", "Framerate datapoints" } }, - { emu_settings_type::PerfOverlayFrametimeDatapoints, { "Video", "Performance Overlay", "Frametime datapoints" } }, - { emu_settings_type::PerfOverlayDetailLevel, { "Video", "Performance Overlay", "Detail level" } }, - { emu_settings_type::PerfOverlayFramerateDetailLevel, { "Video", "Performance Overlay", "Framerate graph detail level" } }, - { emu_settings_type::PerfOverlayFrametimeDetailLevel, { "Video", "Performance Overlay", "Frametime graph detail level" } }, - { emu_settings_type::PerfOverlayPosition, { "Video", "Performance Overlay", "Position" } }, - { emu_settings_type::PerfOverlayUpdateInterval, { "Video", "Performance Overlay", "Metrics update interval (ms)" } }, - { emu_settings_type::PerfOverlayFontSize, { "Video", "Performance Overlay", "Font size (px)" } }, - { emu_settings_type::PerfOverlayOpacity, { "Video", "Performance Overlay", "Opacity (%)" } }, - { emu_settings_type::PerfOverlayMarginX, { "Video", "Performance Overlay", "Horizontal Margin (%)" } }, - { emu_settings_type::PerfOverlayMarginY, { "Video", "Performance Overlay", "Vertical Margin (%)" } }, - { emu_settings_type::PerfOverlayCenterX, { "Video", "Performance Overlay", "Center Horizontally" } }, - { emu_settings_type::PerfOverlayCenterY, { "Video", "Performance Overlay", "Center Vertically" } }, - { emu_settings_type::PerfOverlayUseWindowSpace, { "Video", "Performance Overlay", "Use Window Space"}}, - - // Shader Loading Dialog - { emu_settings_type::ShaderLoadBgEnabled, { "Video", "Shader Loading Dialog", "Allow custom background" } }, - { emu_settings_type::ShaderLoadBgDarkening, { "Video", "Shader Loading Dialog", "Darkening effect strength" } }, - { emu_settings_type::ShaderLoadBgBlur, { "Video", "Shader Loading Dialog", "Blur effect strength" } }, - - // Audio - { emu_settings_type::AudioRenderer, { "Audio", "Renderer"}}, - { emu_settings_type::DumpToFile, { "Audio", "Dump to file"}}, - { emu_settings_type::ConvertTo16Bit, { "Audio", "Convert to 16 bit"}}, - { emu_settings_type::AudioFormat, { "Audio", "Audio Format"}}, - { emu_settings_type::AudioFormats, { "Audio", "Audio Formats"}}, - { emu_settings_type::AudioProvider, { "Audio", "Audio Provider"}}, - { emu_settings_type::AudioAvport, { "Audio", "RSXAudio Avport"}}, - { emu_settings_type::AudioDevice, { "Audio", "Audio Device"}}, - { emu_settings_type::AudioChannelLayout, { "Audio", "Audio Channel Layout"}}, - { emu_settings_type::MasterVolume, { "Audio", "Master Volume"}}, - { emu_settings_type::EnableBuffering, { "Audio", "Enable Buffering"}}, - { emu_settings_type::AudioBufferDuration, { "Audio", "Desired Audio Buffer Duration"}}, - { emu_settings_type::EnableTimeStretching, { "Audio", "Enable Time Stretching"}}, - { emu_settings_type::TimeStretchingThreshold, { "Audio", "Time Stretching Threshold"}}, - { emu_settings_type::MicrophoneType, { "Audio", "Microphone Type" }}, - { emu_settings_type::MicrophoneDevices, { "Audio", "Microphone Devices" }}, - { emu_settings_type::MusicHandler, { "Audio", "Music Handler"}}, - - // Input / Output - { emu_settings_type::BackgroundInput, { "Input/Output", "Background input enabled"}}, - { emu_settings_type::ShowMoveCursor, { "Input/Output", "Show move cursor"}}, - { emu_settings_type::LockOvlIptToP1, { "Input/Output", "Lock overlay input to player one"}}, - { emu_settings_type::PadHandlerMode, { "Input/Output", "Pad handler mode"}}, - { emu_settings_type::PadConnection, { "Input/Output", "Keep pads connected" }}, - { emu_settings_type::KeyboardHandler, { "Input/Output", "Keyboard"}}, - { emu_settings_type::MouseHandler, { "Input/Output", "Mouse"}}, - { emu_settings_type::Camera, { "Input/Output", "Camera"}}, - { emu_settings_type::CameraType, { "Input/Output", "Camera type"}}, - { emu_settings_type::CameraFlip, { "Input/Output", "Camera flip"}}, - { emu_settings_type::CameraID, { "Input/Output", "Camera ID"}}, - { emu_settings_type::Move, { "Input/Output", "Move" }}, - { emu_settings_type::Buzz, { "Input/Output", "Buzz emulated controller" }}, - { emu_settings_type::Turntable, { "Input/Output", "Turntable emulated controller" }}, - { emu_settings_type::GHLtar, { "Input/Output", "GHLtar emulated controller" }}, - { emu_settings_type::MidiDevices, { "Input/Output", "Emulated Midi devices" }}, - { emu_settings_type::SDLMappings, { "Input/Output", "Load SDL GameController Mappings" }}, - { emu_settings_type::IoDebugOverlay, { "Input/Output", "IO Debug overlay" }}, - { emu_settings_type::MouseDebugOverlay, { "Input/Output", "Mouse Debug overlay" }}, - - // Misc - { emu_settings_type::ExitRPCS3OnFinish, { "Miscellaneous", "Exit RPCS3 when process finishes" }}, - { emu_settings_type::StartOnBoot, { "Miscellaneous", "Automatically start games after boot" }}, - { emu_settings_type::PauseOnFocusLoss, { "Miscellaneous", "Pause emulation on RPCS3 focus loss" }}, - { emu_settings_type::StartGameFullscreen, { "Miscellaneous", "Start games in fullscreen mode"}}, - { emu_settings_type::PreventDisplaySleep, { "Miscellaneous", "Prevent display sleep while running games"}}, - { emu_settings_type::ShowTrophyPopups, { "Miscellaneous", "Show trophy popups"}}, - { emu_settings_type::ShowRpcnPopups, { "Miscellaneous", "Show RPCN popups"}}, - { emu_settings_type::UseNativeInterface, { "Miscellaneous", "Use native user interface"}}, - { emu_settings_type::ShowShaderCompilationHint, { "Miscellaneous", "Show shader compilation hint"}}, - { emu_settings_type::ShowPPUCompilationHint, { "Miscellaneous", "Show PPU compilation hint"}}, - { emu_settings_type::ShowAutosaveAutoloadHint, { "Miscellaneous", "Show autosave/autoload hint"}}, - { emu_settings_type::ShowPressureIntensityToggleHint, { "Miscellaneous", "Show pressure intensity toggle hint"}}, - { emu_settings_type::ShowAnalogLimiterToggleHint, { "Miscellaneous", "Show analog limiter toggle hint"}}, - { emu_settings_type::ShowMouseAndKeyboardToggleHint, { "Miscellaneous", "Show mouse and keyboard toggle hint"}}, - { emu_settings_type::ShowFatalErrorHints, { "Miscellaneous", "Show fatal error hints"}}, - { emu_settings_type::ShowCaptureHints, { "Miscellaneous", "Show capture hints" }}, - { emu_settings_type::SilenceAllLogs, { "Miscellaneous", "Silence All Logs" }}, - { emu_settings_type::WindowTitleFormat, { "Miscellaneous", "Window Title Format" }}, - { emu_settings_type::PauseDuringHomeMenu, { "Miscellaneous", "Pause Emulation During Home Menu" }}, - { emu_settings_type::PlayMusicDuringBoot, { "Miscellaneous", "Play music during boot sequence" }}, - { emu_settings_type::EnableGamemode, { "Miscellaneous", "Enable GameMode" }}, - - // Networking - { emu_settings_type::InternetStatus, { "Net", "Internet enabled"}}, - { emu_settings_type::DNSAddress, { "Net", "DNS address"}}, - { emu_settings_type::IpSwapList, { "Net", "IP swap list"}}, - { emu_settings_type::PSNStatus, { "Net", "PSN status"}}, - { emu_settings_type::BindAddress, { "Net", "Bind address"}}, - { emu_settings_type::EnableUpnp, { "Net", "UPNP Enabled"}}, - { emu_settings_type::PSNCountry, { "Net", "PSN Country"}}, - { emu_settings_type::EnableClans, { "Net", "Clans Enabled"}}, - - // System - { emu_settings_type::LicenseArea, { "System", "License Area"}}, - { emu_settings_type::Language, { "System", "Language"}}, - { emu_settings_type::KeyboardType, { "System", "Keyboard Type"}}, - { emu_settings_type::EnterButtonAssignment, { "System", "Enter button assignment"}}, - { emu_settings_type::DateFormat, { "System", "Date Format"}}, - { emu_settings_type::TimeFormat, { "System", "Time Format"}}, - { emu_settings_type::ConsoleTimeOffset, { "System", "Console time offset (s)"}}, - - { emu_settings_type::EnableHostRoot, { "VFS", "Enable /host_root/"}}, - { emu_settings_type::EmptyHdd0Tmp, { "VFS", "Empty /dev_hdd0/tmp/"}}, - { emu_settings_type::LimitCacheSize, { "VFS", "Limit disk cache size"}}, - { emu_settings_type::MaximumCacheSize, { "VFS", "Disk cache maximum size (MB)"}}, - - // Savestates - { emu_settings_type::SuspendEmulationSavestateMode, { "Savestate", "Suspend Emulation Savestate Mode" }}, - { emu_settings_type::CompatibleEmulationSavestateMode, { "Savestate", "Compatible Savestate Mode" }}, - { emu_settings_type::StartSavestatePaused, { "Savestate", "Start Paused" }}, - - // Logs - { emu_settings_type::Log, { "Log" }}, -}; +extern const std::map settings_location; diff --git a/rpcs3/rpcs3qt/game_list_context_menu.cpp b/rpcs3/rpcs3qt/game_list_context_menu.cpp index 05fc9fdb8d..f8a26d3f80 100644 --- a/rpcs3/rpcs3qt/game_list_context_menu.cpp +++ b/rpcs3/rpcs3qt/game_list_context_menu.cpp @@ -12,6 +12,7 @@ #include "patch_manager_dialog.h" #include "persistent_settings.h" #include "config_database.h" +#include "config_checker.h" #include "Utilities/File.h" #include "Emu/system_utils.hpp" @@ -167,6 +168,26 @@ void game_list_context_menu::show_single_selection_context_menu(const game_info& QAction* pad_configure = addAction(gameinfo->has_custom_pad_config ? tr("&Change Custom Gamepad Configuration") : tr("&Create Custom Gamepad Configuration")); + + QAction* compare_config = addAction(tr("&Compare Configurations")); + connect(compare_config, &QAction::triggered, this, [this, serial]() + { + std::string db_config; + if (config_database* db = m_game_list_frame->GetConfigDatabase(); db->has_config(serial)) + { + if (const std::optional config = db->get_config(serial)) + { + db_config = *config; + } + else + { + game_list_log.error("No database config found for '%s'", serial); + } + } + config_checker* dlg = new config_checker(m_game_list_frame, QString::fromStdString(serial), config_checker::checker_mode::gamelist, db_config); + dlg->open(); + }); + QAction* configure_patches = addAction(tr("&Manage Game Patches")); addSeparator(); diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 8379e2f5e0..756dbe18ed 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -640,13 +640,15 @@ void gui_application::InitializeCallbacks() on_exit(); } + const bool no_gui = !m_main_window; + if (m_main_window) { // Close main window in order to save its window state m_main_window->close(); } - gui_log.notice("Quitting gui application"); + gui_log.notice("Quitting gui application (force_quit=%d, no-gui=%d)", force_quit, no_gui); quit(); return true; } diff --git a/rpcs3/rpcs3qt/log_viewer.cpp b/rpcs3/rpcs3qt/log_viewer.cpp index b69c07901e..623a74b48a 100644 --- a/rpcs3/rpcs3qt/log_viewer.cpp +++ b/rpcs3/rpcs3qt/log_viewer.cpp @@ -201,7 +201,7 @@ void log_viewer::show_context_menu(const QPoint& pos) connect(config, &QAction::triggered, this, [this]() { - config_checker* dlg = new config_checker(this, m_full_log, true); + config_checker* dlg = new config_checker(this, m_full_log, config_checker::checker_mode::log); dlg->open(); }); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 0bf6a060e1..9dd437b535 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -557,7 +557,7 @@ void main_window::Boot(const std::string& path, const std::string& title_id, boo // Get database config if possible or if we are in database_config mode (to ensure we see an error on invalid use) if (config_database* db = m_game_list_frame->GetConfigDatabase(); - db->has_config(title_id) || config_mode == cfg_mode::database_config) + db->has_config(title_id)) { const std::optional config = db->get_config(title_id); @@ -984,7 +984,7 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo const game_compatibility* compat = m_game_list_frame ? m_game_list_frame->GetGameCompatibility() : nullptr; // Let the user choose the packages to install and select the order in which they shall be installed. - pkg_install_dialog dlg(file_paths, compat, this); + pkg_install_dialog dlg(file_paths, from_boot, compat, this); connect(&dlg, &QDialog::finished, this, [&](int result) { if (result != QDialog::Accepted) @@ -1009,7 +1009,8 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo if (canceled) { - return false; + // return "true" if installation of optional packages (requested by some games at first boot) is skipped + return from_boot; } if (!from_boot) @@ -3249,7 +3250,7 @@ void main_window::CreateConnects() m_gui_settings->SetValue(gui::fd_cfg_check, file_info.path()); - config_checker* dlg = new config_checker(this, content, file_path.endsWith(".log") || file_path.endsWith(".log.gz")); + config_checker* dlg = new config_checker(this, content, (file_path.endsWith(".log") || file_path.endsWith(".log.gz")) ? config_checker::checker_mode::log : config_checker::checker_mode::config); dlg->open(); }); @@ -3943,6 +3944,7 @@ void main_window::closeEvent(QCloseEvent* closeEvent) Q_EMIT NotifyWindowCloseEvent(true); + gui_log.notice("Quit with main_window::closeEvent"); Emu.Quit(true); } diff --git a/rpcs3/rpcs3qt/pkg_install_dialog.cpp b/rpcs3/rpcs3qt/pkg_install_dialog.cpp index a97f656153..a1ebb9a8d1 100644 --- a/rpcs3/rpcs3qt/pkg_install_dialog.cpp +++ b/rpcs3/rpcs3qt/pkg_install_dialog.cpp @@ -24,7 +24,7 @@ enum Roles DataSizeRole = Qt::UserRole + 5, }; -pkg_install_dialog::pkg_install_dialog(const QStringList& paths, const game_compatibility* compat, QWidget* parent) +pkg_install_dialog::pkg_install_dialog(const QStringList& paths, bool from_boot, const game_compatibility* compat, QWidget* parent) : QDialog(parent) { ensure(!paths.empty()); @@ -148,6 +148,11 @@ pkg_install_dialog::pkg_install_dialog(const QStringList& paths, const game_comp buttons->button(QDialogButtonBox::Ok)->setText(tr("Install")); buttons->button(QDialogButtonBox::Ok)->setDefault(true); + if (from_boot) + { + buttons->button(QDialogButtonBox::Cancel)->setText(tr("Skip")); + } + m_dir_list->sortItems(); m_dir_list->setCurrentRow(0); m_dir_list->setMinimumWidth((m_dir_list->sizeHintForColumn(0) * 125) / 100); diff --git a/rpcs3/rpcs3qt/pkg_install_dialog.h b/rpcs3/rpcs3qt/pkg_install_dialog.h index a6174276c3..979d7f5682 100644 --- a/rpcs3/rpcs3qt/pkg_install_dialog.h +++ b/rpcs3/rpcs3qt/pkg_install_dialog.h @@ -17,7 +17,7 @@ class pkg_install_dialog : public QDialog Q_OBJECT public: - explicit pkg_install_dialog(const QStringList& paths, const game_compatibility* compat, QWidget* parent = nullptr); + explicit pkg_install_dialog(const QStringList& paths, bool from_boot, const game_compatibility* compat, QWidget* parent = nullptr); std::vector get_paths_to_install() const; bool precompile_caches() const { return m_precompile_caches; } bool create_desktop_shortcuts() const { return m_create_desktop_shortcuts; }