From 5ff0d0d4325080e7640d2d209f0c821371f951fe Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 16 Jun 2025 15:52:03 -0400 Subject: [PATCH 01/20] Built with set GameMode Param. Will implement toggle logic --- CMakeLists.txt | 8 ++++++++ rpcs3/rpcs3qt/emu_settings_type.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f633730fc..7f62fa187d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,14 @@ if(NOT WIN32) add_compile_options(-pthread) endif() +## Look for Gamemode if its installed on Linux +if(LINUX) + find_program(GAMEMODE_FOUND gamemoded) ## Only works if gamemode is installed on system (might include lib32 case) + if(GAMEMODE_FOUND) + set(GAMEMODE_AVAILABLE ON CACHE BOOL "GameMode is only available on Linux." FORCE) + endif() +endif() + # TODO: do real installation, including copying directory structure set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin") diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 0fda096705..8227d5e36f 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -187,6 +187,8 @@ enum class emu_settings_type WindowTitleFormat, PauseDuringHomeMenu, + //EnableGamemode, // Only available if Feral Interactive GameMode is installed + // Network InternetStatus, DNSAddress, @@ -388,6 +390,7 @@ inline static const std::map settings_location { 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::EnableGamemode, { "Miscellaneous", "Enable GameMode" }} // Networking { emu_settings_type::InternetStatus, { "Net", "Internet enabled"}}, From b869526e9fdbe5f370596bc425bfdeb32faa1bd6 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 16 Jun 2025 16:06:54 -0400 Subject: [PATCH 02/20] Replaced SET with ADD_COMPILE_DEF for defining GAMEMODE_AVAILABLE --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f62fa187d..b14d5ef333 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ endif() if(LINUX) find_program(GAMEMODE_FOUND gamemoded) ## Only works if gamemode is installed on system (might include lib32 case) if(GAMEMODE_FOUND) - set(GAMEMODE_AVAILABLE ON CACHE BOOL "GameMode is only available on Linux." FORCE) + add_compile_definitions(GAMEMODE_AVAILABLE) endif() endif() From 6164fd8e66618a1f4e915c305c7fd0a1cdc292b9 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 17 Jun 2025 16:31:55 -0400 Subject: [PATCH 03/20] Added Toggle Button for GameMode in Emulator Settings Tab. Need to implement Qt connect functionality --- rpcs3/rpcs3qt/emu_settings_type.h | 9 +++++++-- rpcs3/rpcs3qt/settings_dialog.cpp | 5 +++++ rpcs3/rpcs3qt/settings_dialog.ui | 7 +++++++ rpcs3/rpcs3qt/tooltips.h | 4 ++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 8227d5e36f..8f8511510c 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -187,7 +187,9 @@ enum class emu_settings_type WindowTitleFormat, PauseDuringHomeMenu, - //EnableGamemode, // Only available if Feral Interactive GameMode is installed +#ifdef GAMEMODE_AVAILABLE + EnableGamemode, // Only available if Feral Interactive GameMode is installed +#endif // Network InternetStatus, @@ -390,7 +392,10 @@ inline static const std::map settings_location { 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::EnableGamemode, { "Miscellaneous", "Enable GameMode" }} + +#ifdef GAMEMODE_AVAILABLE + { emu_settings_type::EnableGamemode, { "Miscellaneous", "Enable GameMode" }}, +#endif // Networking { emu_settings_type::InternetStatus, { "Net", "Internet enabled"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index abea4b47bf..4252fde3e9 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1848,6 +1848,11 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->useNativeInterface, emu_settings_type::UseNativeInterface); SubscribeTooltip(ui->useNativeInterface, tooltips.settings.use_native_interface); +#ifdef GAMEMODE_AVAILABLE + m_emu_settings->EnhanceCheckBox(ui->enableGamemode, emu_settings_type::EnableGamemode); + SubscribeTooltip(ui->enableGamemode, tooltips.settings.enable_gamemode); +#endif + m_emu_settings->EnhanceCheckBox(ui->showShaderCompilationHint, emu_settings_type::ShowShaderCompilationHint); SubscribeTooltip(ui->showShaderCompilationHint, tooltips.settings.show_shader_compilation_hint); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 7a3d4951a8..6922ec7332 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -3022,6 +3022,13 @@ + + + + Enable GameMode + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 41cfc1e6d8..f7f9fa1796 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -129,6 +129,10 @@ public: // emulator + // GAMEMODE CHANGES + const QString enable_gamemode = tr("Activate Feral Interactive's GameMode.\nThis is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems.\nIf unsure, leave off. \n"); + // + const QString exit_on_stop = tr("Automatically close RPCS3 when closing a game, or when a game closes itself."); const QString pause_on_focus_loss = tr("Automatically pause emulation when RPCS3 loses its focus or the application is inactive in order to save power and reduce CPU usage.\nDo note that emulation pausing in general is not perfect and may not be compatible with all games.\nAlthough it currently also pauses gameplay, it is not recommended to rely on it as this behavior may be changed in the future and it is not the purpose of this setting."); const QString start_game_fullscreen = tr("Automatically puts the game window in fullscreen.\nDouble click on the game window or press Alt+Enter to toggle fullscreen and windowed mode."); From 98588a20d8adfe5e66f85a63897e50a9510cb749 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 17 Jun 2025 17:58:22 -0400 Subject: [PATCH 04/20] Added Build MSG to show that Gamemode is available --- CMakeLists.txt | 1 + rpcs3/rpcs3qt/emu_settings_type.h | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b14d5ef333..db66d916b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,7 @@ if(LINUX) find_program(GAMEMODE_FOUND gamemoded) ## Only works if gamemode is installed on system (might include lib32 case) if(GAMEMODE_FOUND) add_compile_definitions(GAMEMODE_AVAILABLE) + message(GAMEMODE_AVAILABLE="${GAMEMODE_AVAILABLE}") endif() endif() diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 8f8511510c..e175264f87 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -187,9 +187,9 @@ enum class emu_settings_type WindowTitleFormat, PauseDuringHomeMenu, -#ifdef GAMEMODE_AVAILABLE + EnableGamemode, // Only available if Feral Interactive GameMode is installed -#endif + // Network InternetStatus, @@ -393,9 +393,9 @@ inline static const std::map settings_location { emu_settings_type::WindowTitleFormat, { "Miscellaneous", "Window Title Format" }}, { emu_settings_type::PauseDuringHomeMenu, { "Miscellaneous", "Pause Emulation During Home Menu" }}, -#ifdef GAMEMODE_AVAILABLE + { emu_settings_type::EnableGamemode, { "Miscellaneous", "Enable GameMode" }}, -#endif + // Networking { emu_settings_type::InternetStatus, { "Net", "Internet enabled"}}, From 2c96c24d05e6b3c9f6c8fa5a5d7bc9c9b1f45bb9 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Tue, 17 Jun 2025 18:13:03 -0400 Subject: [PATCH 05/20] Changed where debug message for Gamemode displays in CMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db66d916b5..81b2a84ee6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,8 +157,8 @@ if(LINUX) find_program(GAMEMODE_FOUND gamemoded) ## Only works if gamemode is installed on system (might include lib32 case) if(GAMEMODE_FOUND) add_compile_definitions(GAMEMODE_AVAILABLE) - message(GAMEMODE_AVAILABLE="${GAMEMODE_AVAILABLE}") endif() + message(GAMEMODE_AVAILABLE="${GAMEMODE_AVAILABLE}") endif() # TODO: do real installation, including copying directory structure From 2e0330b407036bd9fc2aac4f9e1c00b0b5982321 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 17 Jun 2025 18:26:50 -0400 Subject: [PATCH 06/20] Attempt to make UI element not visible on non gamemode setups --- rpcs3/rpcs3qt/settings_dialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 4252fde3e9..10e875d791 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1849,6 +1849,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std SubscribeTooltip(ui->useNativeInterface, tooltips.settings.use_native_interface); #ifdef GAMEMODE_AVAILABLE + ui->enableGamemode->setVisible(true); m_emu_settings->EnhanceCheckBox(ui->enableGamemode, emu_settings_type::EnableGamemode); SubscribeTooltip(ui->enableGamemode, tooltips.settings.enable_gamemode); #endif From f1e8bb191d4976d46d3e1bef5dd1314abc48b965 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Tue, 17 Jun 2025 19:17:03 -0400 Subject: [PATCH 07/20] Added conditions for displaying the toggle and related tooltips depending if linux and if gamemode is installed on system --- rpcs3/rpcs3qt/settings_dialog.cpp | 7 ++++++- rpcs3/rpcs3qt/settings_dialog.ui | 12 +++++++++--- rpcs3/rpcs3qt/tooltips.h | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 10e875d791..daa72ccd5c 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1848,10 +1848,15 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->useNativeInterface, emu_settings_type::UseNativeInterface); SubscribeTooltip(ui->useNativeInterface, tooltips.settings.use_native_interface); -#ifdef GAMEMODE_AVAILABLE +#if defined(__linux__) ui->enableGamemode->setVisible(true); +#endif +#if defined(GAMEMODE_AVAILABLE) + ui->enableGamemode->setEnabled(true); m_emu_settings->EnhanceCheckBox(ui->enableGamemode, emu_settings_type::EnableGamemode); SubscribeTooltip(ui->enableGamemode, tooltips.settings.enable_gamemode); +#else + SubscribeTooltip(ui->enableGamemode, tooltips.settings.no_gamemode); #endif m_emu_settings->EnhanceCheckBox(ui->showShaderCompilationHint, emu_settings_type::ShowShaderCompilationHint); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 6922ec7332..2c57a2cf51 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -43,8 +43,8 @@ 0 0 - 821 - 716 + 843 + 865 @@ -54,7 +54,7 @@ - 0 + 7 @@ -3024,6 +3024,12 @@ + + false + + + false + Enable GameMode diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index f7f9fa1796..23cc5808e0 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -130,7 +130,8 @@ public: // emulator // GAMEMODE CHANGES - const QString enable_gamemode = tr("Activate Feral Interactive's GameMode.\nThis is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems.\nIf unsure, leave off. \n"); + const QString enable_gamemode = tr("Activate Feral Interactive's GameMode.\nThis is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems."); + const QString no_gamemode = tr("This requires Feral Interactive's GameMode to be installed.\nGameMode is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems.\nTo install GameMode for your specific Linux distribution, go to the GitHub page:https://github.com/FeralInteractive/gamemode"); // const QString exit_on_stop = tr("Automatically close RPCS3 when closing a game, or when a game closes itself."); From 2689c90fb411c78de86aba3cf0ab694860a772db Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 18 Jun 2025 20:14:49 -0400 Subject: [PATCH 08/20] Toggle button works, need to add functionality --- rpcs3/Emu/system_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 92031a51db..2b35e70cb9 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -358,6 +358,7 @@ struct cfg_root : cfg::node cfg::_bool silence_all_logs{ this, "Silence All Logs", false, true }; cfg::string title_format{ this, "Window Title Format", "FPS: %F | %R | %V | %T [%t]", true }; cfg::_bool pause_during_home_menu{this, "Pause Emulation During Home Menu", false, false }; + cfg::_bool enable_gamemode{ this, "Enable GameMode", false, false }; } misc{ this }; From e784120212e00de2e246d9330231dce037c1a74e Mon Sep 17 00:00:00 2001 From: adas20 Date: Sat, 21 Jun 2025 12:44:52 -0400 Subject: [PATCH 09/20] Added toggle gamemode functionality with connect, added extern bool to System.h to toggle gamemode, added gamemode to third party for import purposes --- 3rdparty/CMakeLists.txt | 3 + 3rdparty/feralinteractive/gamemode_client.h | 376 ++++++++++++++++++++ rpcs3/Emu/System.h | 1 + rpcs3/rpcs3qt/settings_dialog.cpp | 8 + 4 files changed, 388 insertions(+) create mode 100644 3rdparty/feralinteractive/gamemode_client.h diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 6c49a889ba..77e88c7942 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -357,6 +357,9 @@ add_subdirectory(opencv EXCLUDE_FROM_ALL) # FUSION add_subdirectory(fusion EXCLUDE_FROM_ALL) +# FERAL INTERACTIVE +# add_subdirectory(feralinteractive EXCLUDE_FROM_ALL) + # add nice ALIAS targets for ease of use if(USE_SYSTEM_LIBUSB) add_library(3rdparty::libusb ALIAS usb-1.0-shared) diff --git a/3rdparty/feralinteractive/gamemode_client.h b/3rdparty/feralinteractive/gamemode_client.h new file mode 100644 index 0000000000..49c34fb9f7 --- /dev/null +++ b/3rdparty/feralinteractive/gamemode_client.h @@ -0,0 +1,376 @@ +/* + +Copyright (c) 2017-2025, Feral Interactive and the GameMode contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Feral Interactive nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + */ +#ifndef CLIENT_GAMEMODE_H +#define CLIENT_GAMEMODE_H +/* + * GameMode supports the following client functions + * Requests are refcounted in the daemon + * + * int gamemode_request_start() - Request gamemode starts + * 0 if the request was sent successfully + * -1 if the request failed + * + * int gamemode_request_end() - Request gamemode ends + * 0 if the request was sent successfully + * -1 if the request failed + * + * GAMEMODE_AUTO can be defined to make the above two functions apply during static init and + * destruction, as appropriate. In this configuration, errors will be printed to stderr + * + * int gamemode_query_status() - Query the current status of gamemode + * 0 if gamemode is inactive + * 1 if gamemode is active + * 2 if gamemode is active and this client is registered + * -1 if the query failed + * + * int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process + * 0 if the request was sent successfully + * -1 if the request failed + * -2 if the request was rejected + * + * int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process + * 0 if the request was sent successfully + * -1 if the request failed + * -2 if the request was rejected + * + * int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process + * 0 if gamemode is inactive + * 1 if gamemode is active + * 2 if gamemode is active and this client is registered + * -1 if the query failed + * + * const char* gamemode_error_string() - Get an error string + * returns a string describing any of the above errors + * + * Note: All the above requests can be blocking - dbus requests can and will block while the daemon + * handles the request. It is not recommended to make these calls in performance critical code + */ + +#include +#include + +#include +#include + +#include + +#include + +static char internal_gamemode_client_error_string[512] = { 0 }; + +/** + * Load libgamemode dynamically to dislodge us from most dependencies. + * This allows clients to link and/or use this regardless of runtime. + * See SDL2 for an example of the reasoning behind this in terms of + * dynamic versioning as well. + */ +static volatile int internal_libgamemode_loaded = 1; + +/* Typedefs for the functions to load */ +typedef int (*api_call_return_int)(void); +typedef const char *(*api_call_return_cstring)(void); +typedef int (*api_call_pid_return_int)(pid_t); + +/* Storage for functors */ +static api_call_return_int REAL_internal_gamemode_request_start = NULL; +static api_call_return_int REAL_internal_gamemode_request_end = NULL; +static api_call_return_int REAL_internal_gamemode_query_status = NULL; +static api_call_return_cstring REAL_internal_gamemode_error_string = NULL; +static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL; +static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL; +static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL; + +/** + * Internal helper to perform the symbol binding safely. + * + * Returns 0 on success and -1 on failure + */ +__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol( + void *handle, const char *name, void **out_func, size_t func_size, bool required) +{ + void *symbol_lookup = NULL; + char *dl_error = NULL; + + /* Safely look up the symbol */ + symbol_lookup = dlsym(handle, name); + dl_error = dlerror(); + if (required && (dl_error || !symbol_lookup)) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "dlsym failed - %s", + dl_error); + return -1; + } + + /* Have the symbol correctly, copy it to make it usable */ + memcpy(out_func, &symbol_lookup, func_size); + return 0; +} + +/** + * Loads libgamemode and needed functions + * + * Returns 0 on success and -1 on failure + */ +__attribute__((always_inline)) static inline int internal_load_libgamemode(void) +{ + /* We start at 1, 0 is a success and -1 is a fail */ + if (internal_libgamemode_loaded != 1) { + return internal_libgamemode_loaded; + } + + /* Anonymous struct type to define our bindings */ + struct binding { + const char *name; + void **functor; + size_t func_size; + bool required; + } bindings[] = { + { "real_gamemode_request_start", + (void **)&REAL_internal_gamemode_request_start, + sizeof(REAL_internal_gamemode_request_start), + true }, + { "real_gamemode_request_end", + (void **)&REAL_internal_gamemode_request_end, + sizeof(REAL_internal_gamemode_request_end), + true }, + { "real_gamemode_query_status", + (void **)&REAL_internal_gamemode_query_status, + sizeof(REAL_internal_gamemode_query_status), + false }, + { "real_gamemode_error_string", + (void **)&REAL_internal_gamemode_error_string, + sizeof(REAL_internal_gamemode_error_string), + true }, + { "real_gamemode_request_start_for", + (void **)&REAL_internal_gamemode_request_start_for, + sizeof(REAL_internal_gamemode_request_start_for), + false }, + { "real_gamemode_request_end_for", + (void **)&REAL_internal_gamemode_request_end_for, + sizeof(REAL_internal_gamemode_request_end_for), + false }, + { "real_gamemode_query_status_for", + (void **)&REAL_internal_gamemode_query_status_for, + sizeof(REAL_internal_gamemode_query_status_for), + false }, + }; + + void *libgamemode = NULL; + + /* Try and load libgamemode */ + libgamemode = dlopen("libgamemode.so.0", RTLD_NOW); + if (!libgamemode) { + /* Attempt to load unversioned library for compatibility with older + * versions (as of writing, there are no ABI changes between the two - + * this may need to change if ever ABI-breaking changes are made) */ + libgamemode = dlopen("libgamemode.so", RTLD_NOW); + if (!libgamemode) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "dlopen failed - %s", + dlerror()); + internal_libgamemode_loaded = -1; + return -1; + } + } + + /* Attempt to bind all symbols */ + for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) { + struct binding *binder = &bindings[i]; + + if (internal_bind_libgamemode_symbol(libgamemode, + binder->name, + binder->functor, + binder->func_size, + binder->required)) { + internal_libgamemode_loaded = -1; + return -1; + }; + } + + /* Success */ + internal_libgamemode_loaded = 0; + return 0; +} + +/** + * Redirect to the real libgamemode + */ +__attribute__((always_inline)) static inline const char *gamemode_error_string(void) +{ + /* If we fail to load the system gamemode, or we have an error string already, return our error + * string instead of diverting to the system version */ + if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') { + return internal_gamemode_client_error_string; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_error_string != NULL); + + return REAL_internal_gamemode_error_string(); +} + +/** + * Redirect to the real libgamemode + * Allow automatically requesting game mode + * Also prints errors as they happen. + */ +#ifdef GAMEMODE_AUTO +__attribute__((constructor)) +#else +__attribute__((always_inline)) static inline +#endif +int gamemode_request_start(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_request_start != NULL); + + if (REAL_internal_gamemode_request_start() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + return 0; +} + +/* Redirect to the real libgamemode */ +#ifdef GAMEMODE_AUTO +__attribute__((destructor)) +#else +__attribute__((always_inline)) static inline +#endif +int gamemode_request_end(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_request_end != NULL); + + if (REAL_internal_gamemode_request_end() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + return 0; +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_query_status(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_query_status == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_query_status missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_query_status(); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_request_start_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_request_start_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_request_start_for(pid); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_request_end_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_request_end_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_request_end_for(pid); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_query_status_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_query_status_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_query_status_for(pid); +} + +#endif // CLIENT_GAMEMODE_H diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 417bef41b8..76f601e758 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -480,3 +480,4 @@ extern Emulator Emu; extern bool g_use_rtm; extern u64 g_rtm_tx_limit1; extern u64 g_rtm_tx_limit2; +extern b8 g_FERAL_GAMEMODE_ON; diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index daa72ccd5c..65cc630c03 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1855,6 +1855,14 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std ui->enableGamemode->setEnabled(true); m_emu_settings->EnhanceCheckBox(ui->enableGamemode, emu_settings_type::EnableGamemode); SubscribeTooltip(ui->enableGamemode, tooltips.settings.enable_gamemode); + connect(ui->enableGamemode, &QCheckBox::toggled, [this](bool checked) + { + if (checked) { + b8 g_FERAL_GAMEMODE_ON = true; + } else if (!checked) { // Wanted to make toggle functionality clear + b8 g_FERAL_GAMEMODE_ON = false; + } + }); #else SubscribeTooltip(ui->enableGamemode, tooltips.settings.no_gamemode); #endif From ba13e2f5de20f29159c522c1996c9e7cd77b6ec6 Mon Sep 17 00:00:00 2001 From: adas20 Date: Sat, 21 Jun 2025 15:31:52 -0400 Subject: [PATCH 10/20] Adding the gamemode header file triggered various compiler warnings. Need to check with maintainers on next steps. --- rpcs3/Emu/System.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 002075b5fa..a2789849b0 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -63,6 +63,12 @@ #include "llvm/Config/llvm-config.h" #endif +// TODO: Decide what to do with including the header file for GAMEMODE to work + +//#ifdef GAMEMODE_AVAILABLE +//#include "3rdparty/feralinteractive/gamemode_client.h" +//#endif + LOG_CHANNEL(sys_log, "SYS"); // Preallocate 32 MiB From 15f25cf9ae3d3a13cf16e78c17c0d1621c7f7827 Mon Sep 17 00:00:00 2001 From: adas20 Date: Sun, 22 Jun 2025 13:05:55 -0400 Subject: [PATCH 11/20] Reverted UI changes, added Gamemode as a submodule, cleaned up comments as per PR review --- .gitmodules | 4 + 3rdparty/feralinteractive/feralinteractive | 1 + 3rdparty/feralinteractive/gamemode_client.h | 376 -------------------- rpcs3/rpcs3qt/emu_settings_type.h | 6 +- rpcs3/rpcs3qt/settings_dialog.cpp | 8 - rpcs3/rpcs3qt/settings_dialog.ui | 6 +- rpcs3/rpcs3qt/tooltips.h | 5 +- 7 files changed, 10 insertions(+), 396 deletions(-) create mode 160000 3rdparty/feralinteractive/feralinteractive delete mode 100644 3rdparty/feralinteractive/gamemode_client.h diff --git a/.gitmodules b/.gitmodules index 427c61ffbd..6f0cd78a5b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -108,3 +108,7 @@ path = 3rdparty/GPUOpen/VulkanMemoryAllocator url = ../../GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git ignore = dirty +[submodule "3rdparty/feralinteractive/feralinteractive"] + path = 3rdparty/feralinteractive/feralinteractive + url = ../../FeralInteractive/gamemode.git + ignore = dirty diff --git a/3rdparty/feralinteractive/feralinteractive b/3rdparty/feralinteractive/feralinteractive new file mode 160000 index 0000000000..af07e169d5 --- /dev/null +++ b/3rdparty/feralinteractive/feralinteractive @@ -0,0 +1 @@ +Subproject commit af07e169d58b574fac2a093296aa37605313bb2b diff --git a/3rdparty/feralinteractive/gamemode_client.h b/3rdparty/feralinteractive/gamemode_client.h deleted file mode 100644 index 49c34fb9f7..0000000000 --- a/3rdparty/feralinteractive/gamemode_client.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - -Copyright (c) 2017-2025, Feral Interactive and the GameMode contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Feral Interactive nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - */ -#ifndef CLIENT_GAMEMODE_H -#define CLIENT_GAMEMODE_H -/* - * GameMode supports the following client functions - * Requests are refcounted in the daemon - * - * int gamemode_request_start() - Request gamemode starts - * 0 if the request was sent successfully - * -1 if the request failed - * - * int gamemode_request_end() - Request gamemode ends - * 0 if the request was sent successfully - * -1 if the request failed - * - * GAMEMODE_AUTO can be defined to make the above two functions apply during static init and - * destruction, as appropriate. In this configuration, errors will be printed to stderr - * - * int gamemode_query_status() - Query the current status of gamemode - * 0 if gamemode is inactive - * 1 if gamemode is active - * 2 if gamemode is active and this client is registered - * -1 if the query failed - * - * int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process - * 0 if the request was sent successfully - * -1 if the request failed - * -2 if the request was rejected - * - * int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process - * 0 if the request was sent successfully - * -1 if the request failed - * -2 if the request was rejected - * - * int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process - * 0 if gamemode is inactive - * 1 if gamemode is active - * 2 if gamemode is active and this client is registered - * -1 if the query failed - * - * const char* gamemode_error_string() - Get an error string - * returns a string describing any of the above errors - * - * Note: All the above requests can be blocking - dbus requests can and will block while the daemon - * handles the request. It is not recommended to make these calls in performance critical code - */ - -#include -#include - -#include -#include - -#include - -#include - -static char internal_gamemode_client_error_string[512] = { 0 }; - -/** - * Load libgamemode dynamically to dislodge us from most dependencies. - * This allows clients to link and/or use this regardless of runtime. - * See SDL2 for an example of the reasoning behind this in terms of - * dynamic versioning as well. - */ -static volatile int internal_libgamemode_loaded = 1; - -/* Typedefs for the functions to load */ -typedef int (*api_call_return_int)(void); -typedef const char *(*api_call_return_cstring)(void); -typedef int (*api_call_pid_return_int)(pid_t); - -/* Storage for functors */ -static api_call_return_int REAL_internal_gamemode_request_start = NULL; -static api_call_return_int REAL_internal_gamemode_request_end = NULL; -static api_call_return_int REAL_internal_gamemode_query_status = NULL; -static api_call_return_cstring REAL_internal_gamemode_error_string = NULL; -static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL; -static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL; -static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL; - -/** - * Internal helper to perform the symbol binding safely. - * - * Returns 0 on success and -1 on failure - */ -__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol( - void *handle, const char *name, void **out_func, size_t func_size, bool required) -{ - void *symbol_lookup = NULL; - char *dl_error = NULL; - - /* Safely look up the symbol */ - symbol_lookup = dlsym(handle, name); - dl_error = dlerror(); - if (required && (dl_error || !symbol_lookup)) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "dlsym failed - %s", - dl_error); - return -1; - } - - /* Have the symbol correctly, copy it to make it usable */ - memcpy(out_func, &symbol_lookup, func_size); - return 0; -} - -/** - * Loads libgamemode and needed functions - * - * Returns 0 on success and -1 on failure - */ -__attribute__((always_inline)) static inline int internal_load_libgamemode(void) -{ - /* We start at 1, 0 is a success and -1 is a fail */ - if (internal_libgamemode_loaded != 1) { - return internal_libgamemode_loaded; - } - - /* Anonymous struct type to define our bindings */ - struct binding { - const char *name; - void **functor; - size_t func_size; - bool required; - } bindings[] = { - { "real_gamemode_request_start", - (void **)&REAL_internal_gamemode_request_start, - sizeof(REAL_internal_gamemode_request_start), - true }, - { "real_gamemode_request_end", - (void **)&REAL_internal_gamemode_request_end, - sizeof(REAL_internal_gamemode_request_end), - true }, - { "real_gamemode_query_status", - (void **)&REAL_internal_gamemode_query_status, - sizeof(REAL_internal_gamemode_query_status), - false }, - { "real_gamemode_error_string", - (void **)&REAL_internal_gamemode_error_string, - sizeof(REAL_internal_gamemode_error_string), - true }, - { "real_gamemode_request_start_for", - (void **)&REAL_internal_gamemode_request_start_for, - sizeof(REAL_internal_gamemode_request_start_for), - false }, - { "real_gamemode_request_end_for", - (void **)&REAL_internal_gamemode_request_end_for, - sizeof(REAL_internal_gamemode_request_end_for), - false }, - { "real_gamemode_query_status_for", - (void **)&REAL_internal_gamemode_query_status_for, - sizeof(REAL_internal_gamemode_query_status_for), - false }, - }; - - void *libgamemode = NULL; - - /* Try and load libgamemode */ - libgamemode = dlopen("libgamemode.so.0", RTLD_NOW); - if (!libgamemode) { - /* Attempt to load unversioned library for compatibility with older - * versions (as of writing, there are no ABI changes between the two - - * this may need to change if ever ABI-breaking changes are made) */ - libgamemode = dlopen("libgamemode.so", RTLD_NOW); - if (!libgamemode) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "dlopen failed - %s", - dlerror()); - internal_libgamemode_loaded = -1; - return -1; - } - } - - /* Attempt to bind all symbols */ - for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) { - struct binding *binder = &bindings[i]; - - if (internal_bind_libgamemode_symbol(libgamemode, - binder->name, - binder->functor, - binder->func_size, - binder->required)) { - internal_libgamemode_loaded = -1; - return -1; - }; - } - - /* Success */ - internal_libgamemode_loaded = 0; - return 0; -} - -/** - * Redirect to the real libgamemode - */ -__attribute__((always_inline)) static inline const char *gamemode_error_string(void) -{ - /* If we fail to load the system gamemode, or we have an error string already, return our error - * string instead of diverting to the system version */ - if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') { - return internal_gamemode_client_error_string; - } - - /* Assert for static analyser that the function is not NULL */ - assert(REAL_internal_gamemode_error_string != NULL); - - return REAL_internal_gamemode_error_string(); -} - -/** - * Redirect to the real libgamemode - * Allow automatically requesting game mode - * Also prints errors as they happen. - */ -#ifdef GAMEMODE_AUTO -__attribute__((constructor)) -#else -__attribute__((always_inline)) static inline -#endif -int gamemode_request_start(void) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { -#ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); -#endif - return -1; - } - - /* Assert for static analyser that the function is not NULL */ - assert(REAL_internal_gamemode_request_start != NULL); - - if (REAL_internal_gamemode_request_start() < 0) { -#ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); -#endif - return -1; - } - - return 0; -} - -/* Redirect to the real libgamemode */ -#ifdef GAMEMODE_AUTO -__attribute__((destructor)) -#else -__attribute__((always_inline)) static inline -#endif -int gamemode_request_end(void) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { -#ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); -#endif - return -1; - } - - /* Assert for static analyser that the function is not NULL */ - assert(REAL_internal_gamemode_request_end != NULL); - - if (REAL_internal_gamemode_request_end() < 0) { -#ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); -#endif - return -1; - } - - return 0; -} - -/* Redirect to the real libgamemode */ -__attribute__((always_inline)) static inline int gamemode_query_status(void) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } - - if (REAL_internal_gamemode_query_status == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_query_status missing (older host?)"); - return -1; - } - - return REAL_internal_gamemode_query_status(); -} - -/* Redirect to the real libgamemode */ -__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } - - if (REAL_internal_gamemode_request_start_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_request_start_for missing (older host?)"); - return -1; - } - - return REAL_internal_gamemode_request_start_for(pid); -} - -/* Redirect to the real libgamemode */ -__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } - - if (REAL_internal_gamemode_request_end_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_request_end_for missing (older host?)"); - return -1; - } - - return REAL_internal_gamemode_request_end_for(pid); -} - -/* Redirect to the real libgamemode */ -__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid) -{ - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } - - if (REAL_internal_gamemode_query_status_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_query_status_for missing (older host?)"); - return -1; - } - - return REAL_internal_gamemode_query_status_for(pid); -} - -#endif // CLIENT_GAMEMODE_H diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index e175264f87..2504d79dd4 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -186,9 +186,7 @@ enum class emu_settings_type ShowMouseAndKeyboardToggleHint, WindowTitleFormat, PauseDuringHomeMenu, - - - EnableGamemode, // Only available if Feral Interactive GameMode is installed + EnableGamemode, // Network @@ -392,8 +390,6 @@ inline static const std::map settings_location { 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::EnableGamemode, { "Miscellaneous", "Enable GameMode" }}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 65cc630c03..daa72ccd5c 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1855,14 +1855,6 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std ui->enableGamemode->setEnabled(true); m_emu_settings->EnhanceCheckBox(ui->enableGamemode, emu_settings_type::EnableGamemode); SubscribeTooltip(ui->enableGamemode, tooltips.settings.enable_gamemode); - connect(ui->enableGamemode, &QCheckBox::toggled, [this](bool checked) - { - if (checked) { - b8 g_FERAL_GAMEMODE_ON = true; - } else if (!checked) { // Wanted to make toggle functionality clear - b8 g_FERAL_GAMEMODE_ON = false; - } - }); #else SubscribeTooltip(ui->enableGamemode, tooltips.settings.no_gamemode); #endif diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 2c57a2cf51..f13b8344cd 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -43,8 +43,8 @@ 0 0 - 843 - 865 + 821 + 716 @@ -54,7 +54,7 @@ - 7 + 0 diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 23cc5808e0..0ef5ae76ec 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -129,11 +129,8 @@ public: // emulator - // GAMEMODE CHANGES const QString enable_gamemode = tr("Activate Feral Interactive's GameMode.\nThis is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems."); - const QString no_gamemode = tr("This requires Feral Interactive's GameMode to be installed.\nGameMode is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems.\nTo install GameMode for your specific Linux distribution, go to the GitHub page:https://github.com/FeralInteractive/gamemode"); - // - + const QString no_gamemode = tr("This requires Feral Interactive's GameMode to be installed.\nGameMode is a series of CPU and GPU optimizations and can potentially benefit game performance on some systems.\nTo install GameMode for your specific Linux distribution, go to the GitHub page:https://github.com/FeralInteractive/gamemode."); const QString exit_on_stop = tr("Automatically close RPCS3 when closing a game, or when a game closes itself."); const QString pause_on_focus_loss = tr("Automatically pause emulation when RPCS3 loses its focus or the application is inactive in order to save power and reduce CPU usage.\nDo note that emulation pausing in general is not perfect and may not be compatible with all games.\nAlthough it currently also pauses gameplay, it is not recommended to rely on it as this behavior may be changed in the future and it is not the purpose of this setting."); const QString start_game_fullscreen = tr("Automatically puts the game window in fullscreen.\nDouble click on the game window or press Alt+Enter to toggle fullscreen and windowed mode."); From 8ca063fe97d661a9f9fbb6517907d9fc970fe623 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 23 Jun 2025 14:26:47 -0400 Subject: [PATCH 12/20] Added first Feral CMake. Will see if I can use library calls. Likely will need to be updated. --- 3rdparty/CMakeLists.txt | 3 ++- 3rdparty/feralinteractive/CMakeLists.txt | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 3rdparty/feralinteractive/CMakeLists.txt diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 77e88c7942..94c6069271 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -358,7 +358,7 @@ add_subdirectory(opencv EXCLUDE_FROM_ALL) add_subdirectory(fusion EXCLUDE_FROM_ALL) # FERAL INTERACTIVE -# add_subdirectory(feralinteractive EXCLUDE_FROM_ALL) +add_subdirectory(feralinteractive EXCLUDE_FROM_ALL) # add nice ALIAS targets for ease of use if(USE_SYSTEM_LIBUSB) @@ -392,3 +392,4 @@ add_library(3rdparty::miniupnpc ALIAS libminiupnpc-static) add_library(3rdparty::rtmidi ALIAS rtmidi) add_library(3rdparty::opencv ALIAS ${OPENCV_TARGET}) add_library(3rdparty::fusion ALIAS Fusion) +add_library(3rdparty::feralinteractive ALIAS 3rdparty_feralinteractive) diff --git a/3rdparty/feralinteractive/CMakeLists.txt b/3rdparty/feralinteractive/CMakeLists.txt new file mode 100644 index 0000000000..c7b136e5f0 --- /dev/null +++ b/3rdparty/feralinteractive/CMakeLists.txt @@ -0,0 +1,9 @@ +# Feral Interactive + +add_library(3rdparty_feralinteractive INTERFACE) + +if (CMAKE_SYSTEM MATCHES "Linux") + target_include_directories(3rdparty_feralinteractive INTERFACE feralinteractive/lib) + target_compile_definitions(3rdparty_feralinteractive INTERFACE -DGAMEMODE_AVAILABLE) + target_link_libraries(3rdparty_feralinteractive INTERFACE feralinteractive) +endif() From a5ef39762ec6642ffc2babc6f0bc535911bde9de Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 23 Jun 2025 14:37:28 -0400 Subject: [PATCH 13/20] included gamemode header in System.cpp. Will attempt lib calls --- rpcs3/Emu/System.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index a2789849b0..9bbb889a7b 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -63,11 +63,13 @@ #include "llvm/Config/llvm-config.h" #endif -// TODO: Decide what to do with including the header file for GAMEMODE to work - -//#ifdef GAMEMODE_AVAILABLE -//#include "3rdparty/feralinteractive/gamemode_client.h" -//#endif +// GameMode Inclusion +#ifdef GAMEMODE_AVAILABLE +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif +extern "C" { + #include "3rdparty/feralinteractive/feralinteractive/lib/gamemode_client.h" +} LOG_CHANNEL(sys_log, "SYS"); From 75af05be21471f108fa49d17e47f71db4ab3d8a2 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 23 Jun 2025 15:14:05 -0400 Subject: [PATCH 14/20] Added lib to System.cpp --- rpcs3/Emu/System.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 9bbb889a7b..69bdfb5341 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -994,6 +994,13 @@ void Emulator::SetContinuousMode(bool continuous_mode) game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, usz recursion_count) { + if (g_cfg.misc.enable_gamemode) { + u8 s_gamemode_start = gamemode_request_start(); + if(s_gamemode_start < 0 ) { + fprintf(stderr, "gamemode start request failed: %s\n", gamemode_error_string()); + } + } + if (recursion_count == 0 && m_restrict_emu_state_change) { return game_boot_result::currently_restricted; @@ -3059,6 +3066,14 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_stage) { + + if (g_cfg.misc.enable_gamemode) { + u8 s_gamemode_end = gamemode_request_end(); + if(s_gamemode_end < 0 ) { + fprintf(stderr, "gamemode exit request failed: %s\n", gamemode_error_string()); + } + } + static const auto make_ptr = [](auto ptr) { return std::shared_ptr>(ptr); From 7f37a66c9df18bfdaa53ac662ca6ae9651afd466 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 24 Jun 2025 11:07:31 -0400 Subject: [PATCH 15/20] Moved Gamemode Init out of performance critical code and placed in its own files to try and get more performance --- rpcs3/Emu/System.cpp | 20 -------------------- rpcs3/Emu/System.h | 1 - rpcs3/enable_gamemode.cpp | 34 ++++++++++++++++++++++++++++++++++ rpcs3/enable_gamemode.h | 4 ++++ rpcs3/rpcs3.cpp | 1 - 5 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 rpcs3/enable_gamemode.cpp create mode 100644 rpcs3/enable_gamemode.h diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 69bdfb5341..e4a561c522 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -63,13 +63,6 @@ #include "llvm/Config/llvm-config.h" #endif -// GameMode Inclusion -#ifdef GAMEMODE_AVAILABLE -#pragma GCC diagnostic ignored "-Wold-style-cast" -#endif -extern "C" { - #include "3rdparty/feralinteractive/feralinteractive/lib/gamemode_client.h" -} LOG_CHANNEL(sys_log, "SYS"); @@ -994,12 +987,6 @@ void Emulator::SetContinuousMode(bool continuous_mode) game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, usz recursion_count) { - if (g_cfg.misc.enable_gamemode) { - u8 s_gamemode_start = gamemode_request_start(); - if(s_gamemode_start < 0 ) { - fprintf(stderr, "gamemode start request failed: %s\n", gamemode_error_string()); - } - } if (recursion_count == 0 && m_restrict_emu_state_change) { @@ -3067,13 +3054,6 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_stage) { - if (g_cfg.misc.enable_gamemode) { - u8 s_gamemode_end = gamemode_request_end(); - if(s_gamemode_end < 0 ) { - fprintf(stderr, "gamemode exit request failed: %s\n", gamemode_error_string()); - } - } - static const auto make_ptr = [](auto ptr) { return std::shared_ptr>(ptr); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 76f601e758..417bef41b8 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -480,4 +480,3 @@ extern Emulator Emu; extern bool g_use_rtm; extern u64 g_rtm_tx_limit1; extern u64 g_rtm_tx_limit2; -extern b8 g_FERAL_GAMEMODE_ON; diff --git a/rpcs3/enable_gamemode.cpp b/rpcs3/enable_gamemode.cpp new file mode 100644 index 0000000000..d2e7e5cb1a --- /dev/null +++ b/rpcs3/enable_gamemode.cpp @@ -0,0 +1,34 @@ +#include "enable_gamemode.h" + +#ifdef GAMEMODE_AVAILABLE +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif +extern "C" { + #include "3rdparty/feralinteractive/feralinteractive/lib/gamemode_client.h" +} + +// Checks if Gamemode is supported on system +bool gamemode_supported() +{ +#if defined(GAMEMODE_AVAILABLE) + return true +#else + return false; +#endif +} + +// Enables GameMode +// Returns -2 if Gamemode isn't supported. +// Returns the value of gamemode_request_start() otherwise. +// This is either 0 or -1 depending on whether gamemode was successfully enabled or not respectively. +int enable_gamemode(bool enabled) { + if (!gamemode_supported()) { + return -2; + } + + // Enable Gamemode + if (enabled) { + u8 s_gamemode_start = gamemode_request_start(); + return s_gamemode_start; + } +} diff --git a/rpcs3/enable_gamemode.h b/rpcs3/enable_gamemode.h new file mode 100644 index 0000000000..f447a953a4 --- /dev/null +++ b/rpcs3/enable_gamemode.h @@ -0,0 +1,4 @@ +#pragma once + +bool gamemode_supported(); +int enable_gamemode(bool enabled); diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index f7efb7728b..445ee8bfcc 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -1315,7 +1315,6 @@ int run_rpcs3(int argc, char** argv) Emu.Quit(true); return 0; } - // run event loop (maybe only needed for the gui application) return app->exec(); } From 29e7f59eaaadb46f5e0a53aaecd6876e27be8b85 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 24 Jun 2025 11:13:35 -0400 Subject: [PATCH 16/20] Renamed gamemode files to be more specific and restored a missing newline in rpcs3.cpp --- rpcs3/{enable_gamemode.cpp => gamemode_control.cpp} | 2 +- rpcs3/{enable_gamemode.h => gamemode_control.h} | 0 rpcs3/rpcs3.cpp | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) rename rpcs3/{enable_gamemode.cpp => gamemode_control.cpp} (96%) rename rpcs3/{enable_gamemode.h => gamemode_control.h} (100%) diff --git a/rpcs3/enable_gamemode.cpp b/rpcs3/gamemode_control.cpp similarity index 96% rename from rpcs3/enable_gamemode.cpp rename to rpcs3/gamemode_control.cpp index d2e7e5cb1a..9d13f42e97 100644 --- a/rpcs3/enable_gamemode.cpp +++ b/rpcs3/gamemode_control.cpp @@ -1,4 +1,4 @@ -#include "enable_gamemode.h" +#include "gamemode_control.h" #ifdef GAMEMODE_AVAILABLE #pragma GCC diagnostic ignored "-Wold-style-cast" diff --git a/rpcs3/enable_gamemode.h b/rpcs3/gamemode_control.h similarity index 100% rename from rpcs3/enable_gamemode.h rename to rpcs3/gamemode_control.h diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index 445ee8bfcc..f7efb7728b 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -1315,6 +1315,7 @@ int run_rpcs3(int argc, char** argv) Emu.Quit(true); return 0; } + // run event loop (maybe only needed for the gui application) return app->exec(); } From 3488a312108a1f278ad5c14ac6c2e643545f13e8 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 24 Jun 2025 12:35:33 -0400 Subject: [PATCH 17/20] Changed Gamemode setting to be dynamic, added callbacks for Gamemode in system.h. Need to implement fully --- rpcs3/Emu/System.h | 2 ++ rpcs3/Emu/system_config.h | 2 +- rpcs3/gamemode_control.cpp | 23 ++++++++++++++--------- rpcs3/gamemode_control.h | 3 ++- rpcs3/main_application.cpp | 1 + rpcs3/rpcs3qt/gui_application.cpp | 1 + 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 417bef41b8..1053be3b3e 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -112,6 +112,8 @@ struct EmuCallbacks std::function enable_display_sleep; std::function check_microphone_permissions; std::function()> make_video_source; + std::function gamemode_supported; + std::function enable_gamemode; }; namespace utils diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 2b35e70cb9..066f3f5798 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -358,7 +358,7 @@ struct cfg_root : cfg::node cfg::_bool silence_all_logs{ this, "Silence All Logs", false, true }; cfg::string title_format{ this, "Window Title Format", "FPS: %F | %R | %V | %T [%t]", true }; cfg::_bool pause_during_home_menu{this, "Pause Emulation During Home Menu", false, false }; - cfg::_bool enable_gamemode{ this, "Enable GameMode", false, false }; + cfg::_bool enable_gamemode{ this, "Enable GameMode", false, true }; } misc{ this }; diff --git a/rpcs3/gamemode_control.cpp b/rpcs3/gamemode_control.cpp index 9d13f42e97..9ca665cccb 100644 --- a/rpcs3/gamemode_control.cpp +++ b/rpcs3/gamemode_control.cpp @@ -17,18 +17,23 @@ bool gamemode_supported() #endif } -// Enables GameMode -// Returns -2 if Gamemode isn't supported. -// Returns the value of gamemode_request_start() otherwise. -// This is either 0 or -1 depending on whether gamemode was successfully enabled or not respectively. -int enable_gamemode(bool enabled) { +// TODO: Might add later +/* +static int gamemode_status() { + return gamemode_query_status(); +} +*/ + +// Enables and Disables GameMode based on user settings and system +void enable_gamemode(bool enabled) { if (!gamemode_supported()) { - return -2; + return; } - // Enable Gamemode + // Enable and Disable Gamemode if (enabled) { - u8 s_gamemode_start = gamemode_request_start(); - return s_gamemode_start; + gamemode_request_start(); + } else { + gamemode_request_end(); } } diff --git a/rpcs3/gamemode_control.h b/rpcs3/gamemode_control.h index f447a953a4..091bacd676 100644 --- a/rpcs3/gamemode_control.h +++ b/rpcs3/gamemode_control.h @@ -1,4 +1,5 @@ #pragma once bool gamemode_supported(); -int enable_gamemode(bool enabled); +void enable_gamemode(bool enabled); +//static int gamemode_status(); // Might add later TODO diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index 65a8117b7f..137b82d803 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "main_application.h" #include "display_sleep_control.h" +#include "gamemode_control.h" #include "util/types.hpp" #include "util/logs.hpp" diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 82f29fcdbd..970d139782 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -15,6 +15,7 @@ #include "qt_music_handler.h" #include "rpcs3_version.h" #include "display_sleep_control.h" +#include "gamemode_control.h" #ifdef WITH_DISCORD_RPC #include "_discord_utils.h" From 6f63e765a0e94a3ffecb1f57ad5241f3b949108b Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 25 Jun 2025 09:44:31 -0400 Subject: [PATCH 18/20] built with new gamemode, in steps of implementing properly --- rpcs3/gamemode_control.cpp | 2 +- rpcs3/rpcs3qt/CMakeLists.txt | 1 + rpcs3/rpcs3qt/gui_application.cpp | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rpcs3/gamemode_control.cpp b/rpcs3/gamemode_control.cpp index 9ca665cccb..9d5a4268f7 100644 --- a/rpcs3/gamemode_control.cpp +++ b/rpcs3/gamemode_control.cpp @@ -11,7 +11,7 @@ extern "C" { bool gamemode_supported() { #if defined(GAMEMODE_AVAILABLE) - return true + return true; #else return false; #endif diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index c49daf0346..7f7605cb74 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -133,6 +133,7 @@ add_library(rpcs3_ui STATIC welcome_dialog.ui ../display_sleep_control.cpp + ../gamemode_control.cpp ../headless_application.cpp ../main_application.cpp ../module_verifier.cpp diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 970d139782..9f13cfdc41 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -951,6 +951,9 @@ void gui_application::InitializeCallbacks() callbacks.display_sleep_control_supported = [](){ return display_sleep_control_supported(); }; callbacks.enable_display_sleep = [](bool enabled){ enable_display_sleep(enabled); }; + //callbacks.gamemode_supported = [](){ return gamemode_supported(); }; + //callbacks.enable_gamemode = [](bool enabled){ enable_gamemode(enabled); }; + callbacks.check_microphone_permissions = []() { Emu.BlockingCallFromMainThread([]() From 9332aba3346cb2e97b6a586aae387848ad0ab638 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 25 Jun 2025 14:50:20 -0400 Subject: [PATCH 19/20] Fixed performance issues and did a dummy impl --- rpcs3/Emu/System.cpp | 1 - rpcs3/rpcs3qt/gui_application.cpp | 4 ++-- rpcs3/rpcs3qt/main_window.cpp | 11 +++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e4a561c522..ba77d11a17 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -63,7 +63,6 @@ #include "llvm/Config/llvm-config.h" #endif - LOG_CHANNEL(sys_log, "SYS"); // Preallocate 32 MiB diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 9f13cfdc41..14ed3a2c7f 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -951,8 +951,8 @@ void gui_application::InitializeCallbacks() callbacks.display_sleep_control_supported = [](){ return display_sleep_control_supported(); }; callbacks.enable_display_sleep = [](bool enabled){ enable_display_sleep(enabled); }; - //callbacks.gamemode_supported = [](){ return gamemode_supported(); }; - //callbacks.enable_gamemode = [](bool enabled){ enable_gamemode(enabled); }; + callbacks.gamemode_supported = [](){ return gamemode_supported(); }; + callbacks.enable_gamemode = [](bool enabled){ enable_gamemode(enabled); }; callbacks.check_microphone_permissions = []() { diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 1326f112d9..bd49c1fde8 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -96,6 +96,10 @@ #define RPCS3_UPDATE_SUPPORTED #endif +#ifdef GAMEMODE_AVAILABLE +#include "../gamemode_control.h" +#endif + LOG_CHANNEL(gui_log, "GUI"); extern atomic_t g_user_asked_for_frame_capture; @@ -287,6 +291,13 @@ bool main_window::Init([[maybe_unused]] bool with_cli_boot) update_gui_pad_thread(); + // Enable Gamemode +#if defined GAMEMODE_AVAILABLE && defined __linux__ + // NOTE: Compiler complains if I pass the config value directly so I have to do this + if (g_cfg.misc.enable_gamemode) { + enable_gamemode(true); + } +#endif return true; } From 6b2d2e35e4aaa6cd432f497d1c8c9838199e17e0 Mon Sep 17 00:00:00 2001 From: adas20 Date: Fri, 27 Jun 2025 12:29:11 -0400 Subject: [PATCH 20/20] Made Gamemode a non dynamic setting again after thinking about Steam impl. Gamemode Works on normal emulator launch and with custom configs. --- rpcs3/Emu/System.cpp | 5 +++++ rpcs3/Emu/system_config.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index ba77d11a17..fb0667c468 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -2478,6 +2478,11 @@ void Emulator::Run(bool start_playtime) { Emu.GetCallbacks().enable_display_sleep(false); } + + if (g_cfg.misc.enable_gamemode) + { + Emu.GetCallbacks().enable_gamemode(true); + } } void Emulator::RunPPU() diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 066f3f5798..2b35e70cb9 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -358,7 +358,7 @@ struct cfg_root : cfg::node cfg::_bool silence_all_logs{ this, "Silence All Logs", false, true }; cfg::string title_format{ this, "Window Title Format", "FPS: %F | %R | %V | %T [%t]", true }; cfg::_bool pause_during_home_menu{this, "Pause Emulation During Home Menu", false, false }; - cfg::_bool enable_gamemode{ this, "Enable GameMode", false, true }; + cfg::_bool enable_gamemode{ this, "Enable GameMode", false, false }; } misc{ this };