From 75480ffdb51e660ca3ed13c0f8c4aef6819ba0a7 Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Fri, 3 Apr 2026 12:34:15 -0400 Subject: [PATCH] hocclk: fix vrr out of focus --- .../sysmodule/src/board/board_freq.cpp | 5 +- Source/hoc-clk/sysmodule/src/governor.cpp | 19 ++++- .../sysmodule/src/process_management.cpp | 78 ++++++++++++++++++- .../sysmodule/src/process_management.hpp | 1 + 4 files changed, 95 insertions(+), 8 deletions(-) diff --git a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp index bc4d8c6b..5ab9ad9f 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp @@ -222,9 +222,6 @@ namespace board { } void ResetToStockDisplay() { - if (GetConsoleType() != HocClkConsoleType_Hoag) { - display::SetRate(60); - } + display::SetRate(60); } - } diff --git a/Source/hoc-clk/sysmodule/src/governor.cpp b/Source/hoc-clk/sysmodule/src/governor.cpp index e0d16a8c..51edd234 100644 --- a/Source/hoc-clk/sysmodule/src/governor.cpp +++ b/Source/hoc-clk/sysmodule/src/governor.cpp @@ -16,7 +16,7 @@ */ #include "governor.hpp" - +#include "process_management.hpp" namespace governor { #define POLL_NS 5'000'000 // 5 ms – governor poll rate @@ -249,7 +249,7 @@ namespace governor { { (void)arg; - u8 tick = 0; + u8 tick = 0, tick2 = 0; for (;;) { if (!clockManager::gRunning || clockManager::gContext.profile == HocClkProfile_Docked || !isVRREnabled) { svcSleepThread(POLL_NS); @@ -257,6 +257,21 @@ namespace governor { } std::scoped_lock lock{clockManager::gContextMutex}; + + if(++tick2 > 100) { + bool isApplicationOutOfFocus = false; + Result rc = processManagement::isApplicationOutOfFocus(&isApplicationOutOfFocus); + if(R_FAILED(rc)) { + svcSleepThread(POLL_NS); + continue; + } + + if(isApplicationOutOfFocus) { + board::ResetToStockDisplay(); + svcSleepThread(POLL_NS); + continue; + } + } u8 fps; diff --git a/Source/hoc-clk/sysmodule/src/process_management.cpp b/Source/hoc-clk/sysmodule/src/process_management.cpp index a06ac0a3..1d3ffbdd 100644 --- a/Source/hoc-clk/sysmodule/src/process_management.cpp +++ b/Source/hoc-clk/sysmodule/src/process_management.cpp @@ -28,12 +28,14 @@ #include "process_management.hpp" #include "file_utils.hpp" #include "errors.hpp" +#include namespace processManagement { namespace { constexpr u64 Qlaunch = 0x0100000000001000ULL; constexpr u32 IsQlaunch = 0x20f; + Service pdmqryClone; } void Initialize() { @@ -44,10 +46,18 @@ namespace processManagement { rc = pminfoInitialize(); ASSERT_RESULT_OK(rc, "pminfoInitialize"); + + rc = pdmqryInitialize(); + ASSERT_RESULT_OK(rc, "pdmqryInitialize"); + + Service* pdmqrySrv = pdmqryGetServiceSession(); + serviceClone(pdmqrySrv, &pdmqryClone); + serviceClose(pdmqrySrv); + memcpy(pdmqrySrv, &pdmqryClone, sizeof(Service)); + } void WaitForQLaunch() { - Result rc = 0; u64 pid = 0; do { @@ -56,6 +66,69 @@ namespace processManagement { } while (R_FAILED(rc)); } + // Ty to Masa for this function! + Result isApplicationOutOfFocus(bool* outOfFocus) { + static s32 last_total_entries = 0; + static bool isOutOfFocus = false; + s32 total_entries = 0; + s32 start_entry_index = 0; + s32 end_entry_index = 0; + u64 TIDnow; + u64 PIDnow; + + Result rc = pmdmntGetApplicationProcessId(&PIDnow); + if(R_FAILED(rc)) return rc; + rc = pmdmntGetProgramId(&TIDnow, PIDnow); + if(R_FAILED(rc)) return rc; + + rc = pdmqryGetAvailablePlayEventRange(&total_entries, &start_entry_index, &end_entry_index); + if (R_FAILED(rc)) return rc; + if (total_entries == last_total_entries) { + *outOfFocus = isOutOfFocus; + return 0; + } + last_total_entries = total_entries; + + PdmPlayEvent events[16]; + s32 out = 0; + s32 start_entry = end_entry_index - 15; + if (start_entry < 0) start_entry = 0; + rc = pdmqryQueryPlayEvent(start_entry, events, sizeof(events) / sizeof(events[0]), &out); + if (R_FAILED(rc)) return rc; + if (out == 0) return 1; + + int itr = -1; + for (int i = out-1; i >= 0; i--) { + if (events[i].play_event_type != PdmPlayEventType_Applet) + continue; + if (events[i].event_data.applet.applet_id != AppletId_application) + continue; + union { + struct { + uint32_t part[2]; + } parts; + uint64_t full; + } TID; + TID.parts.part[0] = events[i].event_data.applet.program_id[1]; + TID.parts.part[1] = events[i].event_data.applet.program_id[0]; + + + + if (TID.full != (TIDnow & ~0xFFF)) + continue; + else { + itr = i; + break; + } + } + if (itr == -1) return 1; + + bool isOut = events[itr].event_data.applet.event_type == PdmAppletEventType_OutOfFocus || events[itr].event_data.applet.event_type == PdmAppletEventType_OutOfFocus4; + *outOfFocus = isOut; + isOutOfFocus = isOut; + return 0; + } + u64 GetCurrentApplicationId() { Result rc = 0; u64 pid = 0; @@ -82,6 +155,7 @@ namespace processManagement { void Exit() { pmdmntExit(); pminfoExit(); + pdmqryExit(); } -} \ No newline at end of file +} diff --git a/Source/hoc-clk/sysmodule/src/process_management.hpp b/Source/hoc-clk/sysmodule/src/process_management.hpp index 579ad29a..f7660076 100644 --- a/Source/hoc-clk/sysmodule/src/process_management.hpp +++ b/Source/hoc-clk/sysmodule/src/process_management.hpp @@ -33,6 +33,7 @@ namespace processManagement { void Initialize(); void WaitForQLaunch(); u64 GetCurrentApplicationId(); + Result isApplicationOutOfFocus(bool* outOfFocus); void Exit(); }