diff options
| author | néo Luigi <85024393+neoluigi4123@users.noreply.github.com> | 2026-10-30 18:04:26 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-10-30 20:27:35 +0100 |
| commit | d2ac2275247a9ecb3e1404606f7026c6402533b8 (patch) | |
| tree | b9842b0cd90729c3745c1285dcbdc8337cba118d /src | |
| parent | 8a72dc011e0a30a6bddd1f2476a94927787e6e15 (diff) | |
Fixed game support about docked/handheld mode, applying only to ns2 games. Tested on windows.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt | 5 | ||||
| -rw-r--r-- | src/core/core.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_manager.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_manager.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/am/lifecycle_manager.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/am/lifecycle_manager.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/application_functions.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/application_functions.h | 2 |
8 files changed, 38 insertions, 7 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt index c2ef683cfd..62c9b5e753 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt @@ -15,6 +15,7 @@ import android.widget.TextView import androidx.drawerlayout.widget.DrawerLayout import com.google.android.material.color.MaterialColors import com.google.android.material.materialswitch.MaterialSwitch +import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting @@ -150,6 +151,10 @@ class QuickSettings(val emulationFragment: EmulationFragment) { switchView.setOnCheckedChangeListener { _, isChecked -> setting.setBoolean(isChecked) saveSettings() + // Lets the running game know it was docked or undocked. + if (setting == BooleanSetting.USE_DOCKED_MODE) { + NativeLibrary.applySettings() + } } switchContainer.setOnClickListener { diff --git a/src/core/core.cpp b/src/core/core.cpp index 64e1d8de06..8f9d18c141 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1059,6 +1059,8 @@ void System::ApplySettings() { if (IsPoweredOn()) { Renderer().RefreshBaseSettings(); + // Frontends switch docked/handheld through the settings; let the running game know. + GetAppletManager().OperationModeChanged(); } } diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index 05bcf6cc05..887c4521fe 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -248,11 +248,16 @@ void AppletManager::RequestExit() { } } +// Frontends call this after any settings change, so only an actual docked/handheld switch is +// passed on. void AppletManager::OperationModeChanged() { std::scoped_lock lk{m_lock}; - if (m_window_system) { - m_window_system->OnOperationModeChanged(); + const bool docked = Settings::IsDockedMode(); + if (!m_window_system || docked == m_docked) { + return; } + m_docked = docked; + m_window_system->OnOperationModeChanged(); } void AppletManager::SetWindowSystem(WindowSystem* window_system) { @@ -262,6 +267,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { if (!m_window_system) { return; } + m_docked = Settings::IsDockedMode(); m_cv.wait(lk, [&] { return m_pending_process != nullptr; }); diff --git a/src/core/hle/service/am/applet_manager.h b/src/core/hle/service/am/applet_manager.h index cd3035de31..bae3ab4269 100644 --- a/src/core/hle/service/am/applet_manager.h +++ b/src/core/hle/service/am/applet_manager.h @@ -58,6 +58,7 @@ private: std::condition_variable m_cv; WindowSystem* m_window_system{}; + bool m_docked{}; // console mode the applets were last told about FrontendAppletParameters m_pending_parameters{}; std::unique_ptr<Process> m_pending_process{}; diff --git a/src/core/hle/service/am/lifecycle_manager.cpp b/src/core/hle/service/am/lifecycle_manager.cpp index 4b003c4696..14c6179949 100644 --- a/src/core/hle/service/am/lifecycle_manager.cpp +++ b/src/core/hle/service/am/lifecycle_manager.cpp @@ -12,7 +12,8 @@ namespace Service::AM { LifecycleManager::LifecycleManager(Core::System& system, KernelHelpers::ServiceContext& context, bool is_application) : m_system_event(context), m_operation_mode_changed_system_event(context), - m_hdcp_state_changed_event(context), m_is_application(is_application) {} + m_operation_mode_refresh_event(context), m_hdcp_state_changed_event(context), + m_is_application(is_application) {} LifecycleManager::~LifecycleManager() = default; @@ -24,6 +25,10 @@ Event& LifecycleManager::GetOperationModeChangedSystemEvent() { return m_operation_mode_changed_system_event; } +Event& LifecycleManager::GetOperationModeRefreshEvent() { + return m_operation_mode_refresh_event; +} + Event& LifecycleManager::GetHDCPStateChangedEvent() { return m_hdcp_state_changed_event; } @@ -152,6 +157,7 @@ void LifecycleManager::OnOperationAndPerformanceModeChanged(Kernel::KernelCore& m_has_performance_mode_changed = true; } m_operation_mode_changed_system_event.Signal(kernel); + m_operation_mode_refresh_event.Signal(kernel); this->SignalSystemEventIfNeeded(kernel); } diff --git a/src/core/hle/service/am/lifecycle_manager.h b/src/core/hle/service/am/lifecycle_manager.h index 15657a36d8..097ad00776 100644 --- a/src/core/hle/service/am/lifecycle_manager.h +++ b/src/core/hle/service/am/lifecycle_manager.h @@ -45,6 +45,7 @@ public: public: Event& GetSystemEvent(); Event& GetOperationModeChangedSystemEvent(); + Event& GetOperationModeRefreshEvent(); Event& GetHDCPStateChangedEvent(); public: @@ -158,6 +159,7 @@ private: private: Event m_system_event; Event m_operation_mode_changed_system_event; + Event m_operation_mode_refresh_event; Event m_hdcp_state_changed_event; std::list<AppletMessage> m_unordered_messages{}; diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index d4f7cd6041..8949c3daf7 100644 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -14,6 +14,7 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/savedata_factory.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/result.h" #include "core/hle/service/am/am_results.h" @@ -114,7 +115,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ {181, nullptr, "UpgradeLaunchRequiredVersion"}, {190, nullptr, "SendServerMaintenanceOverlayNotification"}, {200, nullptr, "GetLastApplicationExitReason"}, - {210, D<&IApplicationFunctions::GetUnknownEvent210>, "Unknown210"}, + {210, D<&IApplicationFunctions::GetOperationModeRefreshEvent>, "GetOperationModeRefreshEvent (guessed)"}, {220, nullptr, "Unknown220"}, // [20.0.0+] {300, nullptr, "CreateMovieWriter"}, // [19.0.0+] {310, nullptr, "Unknown310"}, // [20.0.0+] @@ -539,10 +540,18 @@ Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent( R_SUCCEED(); } -Result IApplicationFunctions::GetUnknownEvent210( +// The Switch 2 nn::oe::GetOperationMode caches the mode and only asks ICommonStateGetter again +// once this event is signaled, so it has to fire on every docked/handheld change. Switch 1 titles +// keep the event that never fires, as its use there is unknown. +Result IApplicationFunctions::GetOperationModeRefreshEvent( OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_DEBUG(Service_AM, "called"); - *out_event = m_applet->unknown_event.GetHandle(); + const auto* process = m_applet->process ? m_applet->process->GetHandle() : nullptr; + if (process != nullptr && process->IsSwitch2()) { + *out_event = m_applet->lifecycle_manager.GetOperationModeRefreshEvent().GetHandle(); + } else { + *out_event = m_applet->unknown_event.GetHandle(); + } R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h index 72bf8998b1..847943502e 100644 --- a/src/core/hle/service/am/service/application_functions.h +++ b/src/core/hle/service/am/service/application_functions.h @@ -81,7 +81,7 @@ private: Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result CreateApplicationAndRequestToStart(u64 application_id); - Result GetUnknownEvent210(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetOperationModeRefreshEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result Unknown320(); Result Unknown321(); Result Unknown330(Out<u8> out); |
