aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornéo Luigi <85024393+neoluigi4123@users.noreply.github.com>2026-10-30 18:04:26 +0100
committerkraibse <33869366+kraibse@users.noreply.github.com>2026-10-30 20:27:35 +0100
commitd2ac2275247a9ecb3e1404606f7026c6402533b8 (patch)
treeb9842b0cd90729c3745c1285dcbdc8337cba118d /src
parent8a72dc011e0a30a6bddd1f2476a94927787e6e15 (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.kt5
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/hle/service/am/applet_manager.cpp10
-rw-r--r--src/core/hle/service/am/applet_manager.h1
-rw-r--r--src/core/hle/service/am/lifecycle_manager.cpp8
-rw-r--r--src/core/hle/service/am/lifecycle_manager.h2
-rw-r--r--src/core/hle/service/am/service/application_functions.cpp15
-rw-r--r--src/core/hle/service/am/service/application_functions.h2
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);