1
0
Fork 0
mirror of https://github.com/hrydgard/ppsspp.git synced 2025-04-02 11:01:50 -04:00
ppsspp/UI/ImDebugger/ImStructViewer.h
kotcrab bf0b8b59a5 Various struct viewer fixes and improvements
- Can't add multiple watches at once from globals
- Removing watch incorrectly affects tree state
- Fix formatting bitfield enum member with 0 value
- Better formatting for non bitfield enums
- More accurate setup instructions
- Improved UI for setting number of pointer elements
- Chunked display for large arrays and pointers
2024-11-23 10:57:42 +01:00

93 lines
2.5 KiB
C++

#pragma once
#include "ext/imgui/imgui.h"
#include "Common/GhidraClient.h"
#include "Core/MIPS/MIPSDebugInterface.h"
// Struct viewer visualizes objects data in game memory using types and symbols fetched from a Ghidra project.
// It also allows to set memory breakpoints and edit field values which is helpful when reverse engineering unknown
// types.
//
// To use this you will need to install an unofficial Ghidra extension "ghidra-rest-api" by Kotcrab.
// (available at https://github.com/kotcrab/ghidra-rest-api). After installing the extension and starting the API
// server in Ghidra you can open the Struct viewer window and press the "Connect" button to start using it.
//
// See the original pull request https://github.com/hrydgard/ppsspp/pull/19629 for a screenshot and how to test this
// without the need to set up Ghidra.
class ImStructViewer {
struct Watch {
int id = 0;
std::string expression;
u32 address = 0;
std::string typePathName;
std::string name;
};
struct NewWatch {
char name[256] = {};
std::string typeDisplayName;
std::string typePathName;
char expression[256] = {};
bool dynamic = false;
std::string error;
ImGuiTextFilter typeFilter;
};
public:
void Draw(MIPSDebugInterface* mipsDebug, bool* open);
private:
MIPSDebugInterface* mipsDebug_ = nullptr;
ImGuiTextFilter globalFilter_;
ImGuiTextFilter watchFilter_;
GhidraClient ghidraClient_;
char ghidraHost_[128] = "localhost";
int ghidraPort_ = 18489;
bool fetchedAtLeastOnce_ = false; // True if fetched from Ghidra successfully at least once
std::vector<Watch> watches_;
int nextWatchId_ = 0; // ID value to use when creating new watch entry
int removeWatchId_ = -1; // Watch entry id to be removed on next draw
Watch addWatch_; // Temporary variable to store watch entry added from the Globals tab
NewWatch newWatch_; // State for the new watch entry UI
void DrawConnectionSetup();
void DrawStructViewer();
void DrawGlobals();
void DrawWatch();
void DrawNewWatchEntry();
void DrawType(
u32 base,
u32 offset,
const std::string& typePathName,
const char* typeDisplayNameOverride,
const char* name,
int watchId,
ImGuiTreeNodeFlags extraTreeNodeFlags = 0);
void DrawIndexedMembers(
u32 base,
u32 offset,
const std::string& typePathName,
const char* name,
u32 elementCount,
int elementLength,
bool openFirst);
void DrawContextMenu(
u32 base,
u32 offset,
int length,
const std::string& typePathName,
const char* name,
int watchId,
const u64* value);
};