From 64c91974f4455a63a025149a4ba8e2c46894bdc7 Mon Sep 17 00:00:00 2001
From: Takoroka <137927095+Takoroka@users.noreply.github.com>
Date: Wed, 28 Oct 2026 04:56:14 -0400
Subject: nx2: frame-locked input replay and quieter logs
EDEN_NX2_KEY_RECORD records keyboard transitions as "f: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.
---
src/core/memory.cpp | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
(limited to 'src/core/memory.cpp')
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index eabc6dfccb..6e0ab0ee6d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -5,6 +5,7 @@
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include
#include
#include
#include
@@ -36,6 +37,11 @@
namespace Core::Memory {
+u32& UnmappedReadFlag() {
+ thread_local u32 flag{};
+ return flag;
+}
+
static inline bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr, const std::size_t size) {
const Common::ProcessAddress max_addr = 1ULL << table.GetAddressSpaceBits();
return addr + size >= addr && addr + size <= max_addr;
@@ -623,7 +629,13 @@ struct Memory::Impl {
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v) {
const u64 addr = GetInteger(vaddr);
if (auto const ptr = GetPointerImpl(addr, [addr]() {
- LOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#016x}", sizeof(T) * 8, addr);
+ // A guest spinning on a bad pointer reads unmapped memory tens of thousands of times
+ // a second: keep the first ones and then a sample.
+ static std::atomic unmapped_reads{};
+ if (const u64 count = unmapped_reads.fetch_add(1); count < 1000 || count % 100000 == 0) {
+ LOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#016x} (#{})", sizeof(T) * 8, addr, count);
+ }
+ ++UnmappedReadFlag();
}, [&]() {
HandleRasterizerDownload(addr, sizeof(T));
}); ptr) [[likely]] {
--
cgit v1.2.3