Files
ppsspp/UI/ImDebugger/ImDebugger.h
T
Henrik RydgårdandClaude Opus 5.5 f982a6a475 Debugger: Fix the Win32 VFPU window at high DPI, implement it in ImDebugger
- Fixes #21636

The Win32 window drew with a fixed 12px font and hardcoded pixel offsets, so at
high DPI the grid ran under the (dialog-unit sized) tab bar. It now uses the
DPI-scaled debugger font, derives the layout from its metrics and the tab bar's
position, and sizes the window to fit. The HalfFloat, Bytes, Shorts and Ints
tabs, which used to show floats, now work.

The ImDebugger VFPU window, which was a TODO, shows the same grid and modes,
with changed values highlighted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:42:06 +02:00

229 lines
5.2 KiB
C++

#pragma once
#include <vector>
#include <string>
#include <set>
#include "ext/imgui/imgui.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"
#include "Common/System/Request.h"
#include "Core/Core.h"
#include "Core/HLE/SocketManager.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/Debugger/Watch.h"
#include "UI/ImDebugger/ImDisasmView.h"
#include "UI/ImDebugger/ImMemView.h"
#include "UI/ImDebugger/ImStructViewer.h"
#include "UI/ImDebugger/ImJitViewer.h"
#include "UI/ImDebugger/ImGe.h"
#include "UI/ImDebugger/ImConsole.h"
#include "UI/ImDebugger/ImCommand.h"
// This is the main state container of the whole Dear ImGUI-based in-game cross-platform debugger.
//
// Code conventions for ImGUI in PPSSPP
// * If windows/objects need state, prefix the class name with Im and just store straight in parent struct
class MIPSDebugInterface;
class GPUCommon;
struct ImConfig;
// Snapshot of the MIPS CPU and other things we want to show diffs off.
struct ImSnapshotState {
u32 gpr[32];
float fpr[32];
float vpr[128];
u32 pc;
u32 lo;
u32 hi;
u32 ll;
};
class IniFile;
struct ImConfig {
// Defaults for saved settings are set in SyncConfig.
bool disasmOpen;
bool demoOpen;
bool gprOpen;
bool fprOpen;
bool vfpuOpen;
bool threadsOpen;
bool callstackOpen;
bool breakpointsOpen;
bool symbolsOpen;
bool modulesOpen;
bool hleModulesOpen;
bool mediaDecodersOpen;
bool structViewerOpen;
bool framebuffersOpen;
bool texturesOpen;
bool displayOpen;
bool styleEditorOpen;
bool filesystemBrowserOpen;
bool kernelObjectsOpen;
bool audioChannelsOpen;
bool debugStatsOpen;
bool geDebuggerOpen;
bool geStateOpen;
bool geVertsOpen;
bool schedulerOpen;
bool timeOpen;
bool watchOpen;
bool pixelViewerOpen;
bool npOpen;
bool socketsOpen;
bool apctlOpen;
bool adhocOpen;
bool memDumpOpen;
bool internalsOpen;
bool sasAudioOpen;
bool logConfigOpen;
bool logOpen;
bool utilityModulesOpen;
bool atracToolOpen;
bool memViewOpen[4];
bool luaConsoleOpen;
bool audioOutOpen;
bool paramSFOOpen;
bool jitViewerOpen;
// HLE explorer settings
// bool filterByUsed = true;
// Various selections
int selectedModuleId = 0;
int selectedSymbolModule = 0;
int selectedUtilityModule = 0;
int selectedThread = 0;
int selectedKernelObject = 0;
int selectedFramebuffer = -1;
int selectedBreakpoint = -1;
int selectedMemCheck = -1;
int selectedRegBreakpoint = -1;
int selectedAtracCtx = 0;
int vfpuDisplayMode = 0;
int selectedMp3Ctx = 0;
int selectedAacCtx = 0;
int selectedMemoryBlock = 0;
u32 selectedMpegCtx = 0;
uint64_t selectedTexId = 0;
bool selectedTexSecondary = false;
bool realtimePixelPreview = false;
int breakCount = 0;
bool displayLatched = false;
int requesterToken;
bool sasShowAllVoices = false;
bool vertexListClipped = false;
float fbViewerZoom = 1.0f;
// We use a separate ini file from the main PPSSPP config.
void LoadConfig(const Path &iniFile);
void SaveConfig(const Path &iniFile);
void SyncConfig(IniFile *ini, bool save);
};
struct Track;
class ImAtracToolWindow {
public:
void Draw(ImConfig &cfg);
void Load();
char atracPath_[1024]{};
std::unique_ptr<Track> track_;
std::string error_;
std::string data_;
};
class ImWatchWindow {
public:
ImWatchWindow();
void Draw(ImConfig &cfg, ImControl &control, MIPSDebugInterface *mipsDebug);
private:
std::vector<WatchInfo> watches_;
char editBuffer_[256];
int editingWatchIndex_ = -1;
int editingColumn_ = 0;
bool setEditFocus_ = false;
};
class ImLogWindow {
public:
ImLogWindow() {}
void Draw(ImConfig &cfg);
private:
bool AutoScroll = true; // Keep scrolling if already at the bottom.
};
class ImDebugger {
public:
ImDebugger();
~ImDebugger();
void Frame(MIPSDebugInterface *mipsDebug, GPUCommon *gpuDebug, Draw::DrawContext *draw);
// Should be called just before starting a step or run, so that things can
// save state that they can later compare with, to highlight changes.
void Snapshot(MIPSState *mips);
void SnapshotGPU(GPUCommon *mips);
// Call from the outside.
void PostCmd(ImCommand cmd) {
externalCommand_ = cmd;
}
void DeviceLost();
private:
Path ConfigPath();
RequesterToken reqToken_;
ImDisasmWindow disasm_;
ImGeDebuggerWindow geDebugger_;
ImGeStateWindow geStateWindow_;
ImMemWindow mem_[4]; // We support 4 separate instances of the memory viewer.
ImStructViewer structViewer_;
ImGePixelViewerWindow pixelViewer_;
ImMemDumpWindow memDumpWindow_;
ImWatchWindow watchWindow_;
ImAtracToolWindow atracToolWindow_;
ImConsole luaConsole_;
ImLogWindow logWindow_;
ImJitViewerWindow jitViewer_;
ImSnapshotState newSnapshot_;
ImSnapshotState snapshot_;
int lastCpuStepCount_ = -1;
int lastGpuStepCount_ = -1;
// Open variables.
ImConfig cfg_{};
ImCommand externalCommand_;
};
// Simple custom controls and utilities.
void ImClickableValue(const char *id, uint32_t value, ImControl &control, ImCmd cmd);
void ImClickableValueFloat(const char *id, float value);
void ShowInWindowMenuItems(uint32_t addr, ImControl &control);
void ShowInMemoryViewerMenuItem(uint32_t addr, ImControl &control);
void ShowInMemoryDumperMenuItem(uint32_t addr, uint32_t size, MemDumpMode mode, ImControl &control);
void StatusBar(std::string_view str);
inline const char *BoolStr(bool s) { return s ? "true" : "false"; }