aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/service/service.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 04:56:14 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 04:56:14 -0400
commit64c91974f4455a63a025149a4ba8e2c46894bdc7 (patch)
tree3712d1c121e020e6a0eabb883f47745bbb8cd89a /src/core/hle/service/service.cpp
parent1517ba02d3247a8deaad9ac493b9ad4a3deb7506 (diff)
nx2: frame-locked input replay and quieter logs
EDEN_NX2_KEY_RECORD records keyboard transitions as "f<frame>:code" against a global count of guest presents; EDEN_NX2_KEY_SCRIPT replays them on the same frames (or by seconds, as before), so a played session reproduces exactly. Debug aids: the PC/LR/SP of the first unmapped reads, NSO load addresses, EDEN_NX2_IPC_SUMMARY (request counts every 5 s), EDEN_NX2_FORCE_LOD0. Unmapped-access logging is rate limited and the per-draw/semaphore spam is demoted, so long sessions stay under the log size cap.
Diffstat (limited to 'src/core/hle/service/service.cpp')
-rw-r--r--src/core/hle/service/service.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 931de1c3ef..df929e8193 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -4,6 +4,13 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "common/scope_exit.h"
+#include <vector>
+#include <tuple>
+#include <mutex>
+#include <map>
+#include <chrono>
+#include <algorithm>
#include <cstdlib>
#include <fmt/ranges.h>
#include "common/assert.h"
@@ -125,9 +132,59 @@ void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) {
handler_invoker(this, info->handler_callback, ctx);
}
+namespace {
+// EDEN_NX2_IPC_SUMMARY: every 5 s, log how often each service command ran and with which result
+// since the last summary (finds a game polling something that never becomes ready).
+void CountRequest(const std::string& service, u32 command, u32 type, u32 result) {
+ static const bool enabled = std::getenv("EDEN_NX2_IPC_SUMMARY") != nullptr;
+ if (!enabled) {
+ return;
+ }
+ static std::mutex mutex;
+ static std::map<std::tuple<std::string, u32, u32, u32>, u32> counts;
+ static auto last = std::chrono::steady_clock::now();
+ std::scoped_lock lock{mutex};
+ ++counts[{service, command, type, result}];
+ const auto now = std::chrono::steady_clock::now();
+ if (now - last < std::chrono::seconds{5}) {
+ return;
+ }
+ last = now;
+ std::vector<std::pair<u32, std::string>> lines;
+ for (const auto& [key, count] : counts) {
+ lines.emplace_back(count, fmt::format("{}::{}{} -> {:#x}", std::get<0>(key), std::get<1>(key),
+ std::get<2>(key) >= 16 ? " (tipc)" : "",
+ std::get<3>(key)));
+ }
+ std::sort(lines.begin(), lines.end(), [](const auto& a, const auto& b) { return a.first > b.first; });
+ std::string text;
+ for (size_t i = 0; i < std::min<size_t>(lines.size(), 24); ++i) {
+ text += fmt::format(" | {}x {}", lines[i].first, lines[i].second);
+ }
+ LOG_INFO(Service, "ipc summary ({} kinds){}", lines.size(), text);
+ counts.clear();
+}
+} // Anonymous namespace
+
Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
HLERequestContext& ctx) {
const auto guard = LockService();
+ SCOPE_EXIT {
+ const auto* cmd_buf = ctx.CommandBuffer();
+ u32 result_word = 0;
+ const u32 type = static_cast<u32>(ctx.GetCommandType());
+ if (type >= 16) {
+ result_word = cmd_buf[2];
+ } else {
+ for (int i = 0; i < 12; ++i) {
+ if (cmd_buf[i] == 0x4F434653) { // "SFCO"
+ result_word = cmd_buf[i + 2];
+ break;
+ }
+ }
+ }
+ CountRequest(service_name, ctx.GetCommand(), type, result_word);
+ };
Result result = ResultSuccess;