mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-25 00:04:49 +02:00
Most of these are entirely static, but introspection is good for APIs.
143 lines
4.9 KiB
C++
143 lines
4.9 KiB
C++
// 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"
|
|
#include "Core/MemMap.h"
|
|
|
|
class WebSocketMemoryInfoState : public DebuggerSubscriber {
|
|
public:
|
|
WebSocketMemoryInfoState() {
|
|
}
|
|
~WebSocketMemoryInfoState() override {
|
|
UpdateOverride(false);
|
|
}
|
|
|
|
void Mapping(DebuggerRequest &req);
|
|
void Config(DebuggerRequest &req);
|
|
|
|
protected:
|
|
void UpdateOverride(bool flag);
|
|
|
|
bool detailOverride_ = false;
|
|
};
|
|
|
|
DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) {
|
|
auto p = new WebSocketMemoryInfoState();
|
|
map["memory.mapping"] = std::bind(&WebSocketMemoryInfoState::Mapping, p, std::placeholders::_1);
|
|
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;
|
|
}
|
|
|
|
// List memory map data (memory.mapping)
|
|
//
|
|
// No parameters.
|
|
//
|
|
// Response (same event name):
|
|
// - ranges: array of objects:
|
|
// - type: one of "ram", "vram", "sram".
|
|
// - subtype: "primary" or "mirror".
|
|
// - name: string, friendly name.
|
|
// - address: number, start address of range.
|
|
// - size: number, in bytes.
|
|
//
|
|
// Note: Even if you set false, may stay enabled if set by user or another debug session.
|
|
void WebSocketMemoryInfoState::Mapping(DebuggerRequest &req) {
|
|
struct MemRange {
|
|
const char *type;
|
|
const char *subtype;
|
|
const char *name;
|
|
const uint32_t address;
|
|
const uint32_t size;
|
|
};
|
|
constexpr uint32_t kernelMemorySize = PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase();
|
|
constexpr uint32_t volatileMemorySize = PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart();
|
|
static constexpr MemRange ranges[] = {
|
|
{ "sram", "primary", "Scratchpad", PSP_GetScratchpadMemoryBase(), Memory::SCRATCHPAD_SIZE },
|
|
{ "vram", "primary", "VRAM", PSP_GetVidMemBase(), Memory::VRAM_SIZE },
|
|
{ "vram", "mirror", "VRAM (Swizzled)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 1, Memory::VRAM_SIZE },
|
|
{ "vram", "mirror", "VRAM (Mirror)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 2, Memory::VRAM_SIZE },
|
|
{ "vram", "mirror", "VRAM (Swizzled + Interleaved)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 3, Memory::VRAM_SIZE },
|
|
{ "ram", "primary", "Kernel Memory", 0x80000000 | PSP_GetKernelMemoryBase(), kernelMemorySize },
|
|
{ "ram", "primary", "Volatile Memory", PSP_GetVolatileMemoryStart(), volatileMemorySize },
|
|
// Size is specially calculated.
|
|
{ "ram", "primary", "User Memory", PSP_GetUserMemoryBase(), 0 },
|
|
};
|
|
|
|
JsonWriter &json = req.Respond();
|
|
json.pushArray("ranges");
|
|
for (auto range : ranges) {
|
|
uint32_t size = range.size;
|
|
if (size == 0) {
|
|
size = Memory::g_MemorySize;
|
|
if (size == 0) {
|
|
size = Memory::RAM_NORMAL_SIZE;
|
|
}
|
|
size -= kernelMemorySize + volatileMemorySize;
|
|
}
|
|
json.pushDict();
|
|
json.writeString("type", range.type);
|
|
json.writeString("subtype", range.subtype);
|
|
json.writeString("name", range.name);
|
|
json.writeUint("address", range.address);
|
|
json.writeUint("size", size);
|
|
json.pop();
|
|
|
|
// Also write the uncached range.
|
|
json.pushDict();
|
|
json.writeString("type", range.type);
|
|
json.writeString("subtype", "mirror");
|
|
json.writeString("name", std::string("Uncached ") + range.name);
|
|
json.writeUint("address", 0x40000000 | range.address);
|
|
json.writeUint("size", size);
|
|
json.pop();
|
|
}
|
|
json.pop();
|
|
}
|
|
|
|
// 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);
|
|
}
|