diff --git a/CMakeLists.txt b/CMakeLists.txt
index 640d323b45..0adcdf1aff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1501,6 +1501,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/Debugger/WebSocket/InputSubscriber.h
Core/Debugger/WebSocket/LogBroadcaster.cpp
Core/Debugger/WebSocket/LogBroadcaster.h
+ Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp
+ Core/Debugger/WebSocket/MemoryInfoSubscriber.h
Core/Debugger/WebSocket/MemorySubscriber.cpp
Core/Debugger/WebSocket/MemorySubscriber.h
Core/Debugger/WebSocket/SteppingBroadcaster.cpp
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 30c555b669..30498dc411 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -442,6 +442,7 @@
+
@@ -988,6 +989,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index f66273cddd..3ae957593a 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -980,6 +980,9 @@
Debugger
+
+ Debugger\WebSocket
+
@@ -1676,6 +1679,9 @@
Debugger
+
+ Debugger\WebSocket
+
diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp
index 96b18bfa52..9377599918 100644
--- a/Core/Debugger/MemBlockInfo.cpp
+++ b/Core/Debugger/MemBlockInfo.cpp
@@ -87,6 +87,7 @@ static MemSlabMap writeMap;
static MemSlabMap textureMap;
static std::vector pendingNotifies;
static std::mutex pendingMutex;
+static int detailedOverride;
MemSlabMap::MemSlabMap() {
Reset();
@@ -373,7 +374,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_
bool needFlush = false;
// When the setting is off, we skip smaller info to keep things fast.
- if (g_Config.bDebugMemInfoDetailed || size >= 0x100) {
+ if (size >= 0x100 || MemBlockInfoDetailed()) {
PendingNotifyMem info{ flags, start, size };
info.ticks = CoreTiming::GetTicks();
info.pc = pc;
@@ -472,3 +473,16 @@ void MemBlockInfoDoState(PointerWrap &p) {
writeMap.DoState(p);
textureMap.DoState(p);
}
+
+// Used by the debugger.
+void MemBlockOverrideDetailed() {
+ detailedOverride++;
+}
+
+void MemBlockReleaseDetailed() {
+ detailedOverride--;
+}
+
+bool MemBlockInfoDetailed() {
+ return g_Config.bDebugMemInfoDetailed || detailedOverride != 0;
+}
diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h
index 4e38c8410d..aec9d03725 100644
--- a/Core/Debugger/MemBlockInfo.h
+++ b/Core/Debugger/MemBlockInfo.h
@@ -68,3 +68,7 @@ std::string GetMemWriteTagAt(uint32_t start, uint32_t size);
void MemBlockInfoInit();
void MemBlockInfoShutdown();
void MemBlockInfoDoState(PointerWrap &p);
+
+void MemBlockOverrideDetailed();
+void MemBlockReleaseDetailed();
+bool MemBlockInfoDetailed();
diff --git a/Core/Debugger/WebSocket.cpp b/Core/Debugger/WebSocket.cpp
index c609e08698..3bd69366d0 100644
--- a/Core/Debugger/WebSocket.cpp
+++ b/Core/Debugger/WebSocket.cpp
@@ -57,6 +57,7 @@
#include "Core/Debugger/WebSocket/GPURecordSubscriber.h"
#include "Core/Debugger/WebSocket/HLESubscriber.h"
#include "Core/Debugger/WebSocket/InputSubscriber.h"
+#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h"
#include "Core/Debugger/WebSocket/MemorySubscriber.h"
#include "Core/Debugger/WebSocket/SteppingSubscriber.h"
@@ -70,6 +71,7 @@ static const std::vector subscribers({
&WebSocketGPURecordInit,
&WebSocketHLEInit,
&WebSocketInputInit,
+ &WebSocketMemoryInfoInit,
&WebSocketMemoryInit,
&WebSocketSteppingInit,
});
diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp
new file mode 100644
index 0000000000..e81fa2d44d
--- /dev/null
+++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp
@@ -0,0 +1,73 @@
+// Copyright (c) 2021- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#include "Core/Debugger/MemBlockInfo.h"
+#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h"
+#include "Core/Debugger/WebSocket/WebSocketUtils.h"
+
+class WebSocketMemoryInfoState : public DebuggerSubscriber {
+public:
+ WebSocketMemoryInfoState() {
+ }
+ ~WebSocketMemoryInfoState() override {
+ UpdateOverride(false);
+ }
+
+ void Config(DebuggerRequest &req);
+
+protected:
+ void UpdateOverride(bool flag);
+
+ bool detailOverride_ = false;
+};
+
+DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) {
+ auto p = new WebSocketMemoryInfoState();
+ map["memory.info.config"] = std::bind(&WebSocketMemoryInfoState::Config, p, std::placeholders::_1);
+
+ return p;
+}
+
+void WebSocketMemoryInfoState::UpdateOverride(bool flag) {
+ if (detailOverride_ && !flag)
+ MemBlockReleaseDetailed();
+ if (!detailOverride_ && flag)
+ MemBlockOverrideDetailed();
+ detailOverride_ = flag;
+}
+
+// Update memory info tracking config (memory.info.config)
+//
+// Parameters:
+// - detailed: optional, boolean to force enable detailed tracking (perf impact.)
+//
+// Response (same event name):
+// - detailed: boolean state of tracking before any changes.
+//
+// Note: Even if you set false, may stay enabled if set by user or another debug session.
+void WebSocketMemoryInfoState::Config(DebuggerRequest &req) {
+ bool setDetailed = req.HasParam("detailed");
+ bool detailed = false;
+ if (!req.ParamBool("detailed", &detailed, DebuggerParamType::OPTIONAL))
+ return;
+
+ JsonWriter &json = req.Respond();
+ json.writeBool("detailed", MemBlockInfoDetailed());
+
+ if (setDetailed)
+ UpdateOverride(detailed);
+}
diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.h b/Core/Debugger/WebSocket/MemoryInfoSubscriber.h
new file mode 100644
index 0000000000..a093c5b693
--- /dev/null
+++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2021- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#pragma once
+
+#include "Core/Debugger/WebSocket/WebSocketUtils.h"
+
+DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map);
diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp
index bccf2ce748..9a34a8ab94 100644
--- a/Core/HLE/sceAtrac.cpp
+++ b/Core/HLE/sceAtrac.cpp
@@ -1257,7 +1257,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3
int avret = swr_convert(atrac->swrCtx_, &out, numSamples, inbuf, numSamples);
if (outbufPtr != 0) {
u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16);
- if (packetAddr != 0 && g_Config.bDebugMemInfoDetailed) {
+ if (packetAddr != 0 && MemBlockInfoDetailed()) {
const std::string tag = "AtracDecode/" + GetMemWriteTagAt(packetAddr, packetSize);
NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size());
NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size());
diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp
index e974f4de54..31de118345 100644
--- a/Core/HW/SasAudio.cpp
+++ b/Core/HW/SasAudio.cpp
@@ -149,7 +149,7 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) {
}
if (readp > origp) {
- if (g_Config.bDebugMemInfoDetailed)
+ if (MemBlockInfoDetailed())
NotifyMemInfo(MemBlockFlags::READ, read_, readp - origp, "SasVagDecoder");
read_ += readp - origp;
}
@@ -582,7 +582,7 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) {
if (outputMode == PSP_SAS_OUTPUTMODE_MIXED) {
// Okay, apply effects processing to the Send buffer.
WriteMixedOutput(outp, inp, leftVol, rightVol);
- if (g_Config.bDebugMemInfoDetailed) {
+ if (MemBlockInfoDetailed()) {
if (inp)
NotifyMemInfo(MemBlockFlags::READ, inAddr, grainSize * sizeof(u16) * 2, "SasMix");
NotifyMemInfo(MemBlockFlags::WRITE, outAddr, grainSize * sizeof(u16) * 2, "SasMix");
diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj
index c72b42d206..77d9054999 100644
--- a/UWP/CoreUWP/CoreUWP.vcxproj
+++ b/UWP/CoreUWP/CoreUWP.vcxproj
@@ -404,6 +404,7 @@
+
@@ -637,6 +638,7 @@
+
diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters
index f324ec0208..1c49dfe521 100644
--- a/UWP/CoreUWP/CoreUWP.vcxproj.filters
+++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters
@@ -697,6 +697,9 @@
Debugger\WebSocket
+
+ Debugger\WebSocket
+
Debugger\WebSocket
@@ -1512,6 +1515,9 @@
Debugger\WebSocket
+
+ Debugger\WebSocket
+
Debugger\WebSocket
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 04a223215c..38aba84863 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -418,6 +418,7 @@ EXEC_AND_LIB_FILES := \
$(SRC)/Core/Debugger/WebSocket/InputSubscriber.cpp \
$(SRC)/Core/Debugger/WebSocket/LogBroadcaster.cpp \
$(SRC)/Core/Debugger/WebSocket/MemorySubscriber.cpp \
+ $(SRC)/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp \
$(SRC)/Core/Debugger/WebSocket/SteppingBroadcaster.cpp \
$(SRC)/Core/Debugger/WebSocket/SteppingSubscriber.cpp \
$(SRC)/Core/Debugger/WebSocket/WebSocketUtils.cpp \