mirror of
https://github.com/izzy2lost/ppsspp.git
synced 2026-03-10 12:43:04 -07:00
GE Debugger: Add address breakpoint conditions.
This commit is contained in:
@@ -16,19 +16,28 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/Math/expression_parser.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
namespace GPUBreakpoints {
|
||||
|
||||
struct BreakpointInfo {
|
||||
bool isConditional;
|
||||
PostfixExpression expression;
|
||||
std::string expressionString;
|
||||
};
|
||||
|
||||
static std::mutex breaksLock;
|
||||
static bool breakCmds[256];
|
||||
static std::set<u32> breakPCs;
|
||||
static std::map<u32, BreakpointInfo> breakPCs;
|
||||
static std::set<u32> breakTextures;
|
||||
static std::set<u32> breakRenderTargets;
|
||||
// Small optimization to avoid a lock/lookup for the common case.
|
||||
@@ -158,8 +167,26 @@ bool IsRenderTargetCmdBreakpoint(u32 op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool HitAddressBreakpoint(u32 pc) {
|
||||
if (breakPCsCount == 0)
|
||||
return false;
|
||||
|
||||
std::lock_guard<std::mutex> guard(breaksLock);
|
||||
auto entry = breakPCs.find(pc);
|
||||
if (entry == breakPCs.end())
|
||||
return false;
|
||||
|
||||
if (entry->second.isConditional) {
|
||||
u32 result = 1;
|
||||
if (!GPUDebugExecExpression(gpuDebug, breakPCs[pc].expression, result))
|
||||
return false;
|
||||
return result != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsBreakpoint(u32 pc, u32 op) {
|
||||
if (IsAddressBreakpoint(pc) || IsOpBreakpoint(op)) {
|
||||
if (HitAddressBreakpoint(pc) || IsOpBreakpoint(op)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -275,13 +302,13 @@ void AddAddressBreakpoint(u32 addr, bool temp) {
|
||||
if (temp) {
|
||||
if (breakPCs.find(addr) == breakPCs.end()) {
|
||||
breakPCsTemp.insert(addr);
|
||||
breakPCs.insert(addr);
|
||||
breakPCs[addr].isConditional = false;
|
||||
}
|
||||
// Already normal breakpoint, let's not make it temporary.
|
||||
} else {
|
||||
// Remove the temporary marking.
|
||||
breakPCsTemp.erase(addr);
|
||||
breakPCs.insert(addr);
|
||||
breakPCs[addr].isConditional = false;
|
||||
}
|
||||
|
||||
breakPCsCount = breakPCs.size();
|
||||
@@ -398,6 +425,44 @@ void RemoveTextureChangeTempBreakpoint() {
|
||||
notifyBreakpoints(HasAnyBreakpoints());
|
||||
}
|
||||
|
||||
static bool SetupCond(BreakpointInfo &bp, const std::string &expression, std::string *error) {
|
||||
bool success = true;
|
||||
if (expression.length() != 0) {
|
||||
if (GPUDebugInitExpression(gpuDebug, expression.c_str(), bp.expression)) {
|
||||
bp.isConditional = true;
|
||||
bp.expressionString = expression;
|
||||
} else {
|
||||
bp.isConditional = false;
|
||||
if (error)
|
||||
*error = getExpressionError();
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
bp.isConditional = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SetAddressBreakpointCond(u32 addr, const std::string &expression, std::string *error) {
|
||||
// Must have one in the first place, make sure it's not temporary.
|
||||
AddAddressBreakpoint(addr);
|
||||
|
||||
std::lock_guard<std::mutex> guard(breaksLock);
|
||||
auto &bp = breakPCs[addr];
|
||||
return SetupCond(breakPCs[addr], expression, error);
|
||||
}
|
||||
|
||||
bool GetAddressBreakpointCond(u32 addr, std::string *expression) {
|
||||
std::lock_guard<std::mutex> guard(breaksLock);
|
||||
auto entry = breakPCs.find(addr);
|
||||
if (entry != breakPCs.end() && entry->second.isConditional) {
|
||||
if (expression)
|
||||
*expression = entry->second.expressionString;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UpdateLastTexture(u32 addr) {
|
||||
lastTexture = addr;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace GPUBreakpoints {
|
||||
void RemoveTextureChangeTempBreakpoint();
|
||||
void RemoveRenderTargetBreakpoint(u32 addr);
|
||||
|
||||
bool SetAddressBreakpointCond(u32 addr, const std::string &expression, std::string *error);
|
||||
bool GetAddressBreakpointCond(u32 addr, std::string *expression);
|
||||
|
||||
void UpdateLastTexture(u32 addr);
|
||||
|
||||
void ClearAllBreakpoints();
|
||||
|
||||
@@ -267,6 +267,17 @@ void CtrlDisplayListView::toggleBreakpoint()
|
||||
SendMessage(GetParent(wnd),WM_GEDBG_TOGGLEPCBREAKPOINT,curAddress,0);
|
||||
}
|
||||
|
||||
void CtrlDisplayListView::PromptBreakpointCond() {
|
||||
std::string expression;
|
||||
GPUBreakpoints::GetAddressBreakpointCond(curAddress, &expression);
|
||||
if (!InputBox_GetString(GetModuleHandle(NULL), wnd, L"Expression", expression, expression))
|
||||
return;
|
||||
|
||||
std::string error;
|
||||
if (!GPUBreakpoints::SetAddressBreakpointCond(curAddress, expression, &error))
|
||||
MessageBox(wnd, ConvertUTF8ToWString(error).c_str(), L"Invalid expression", MB_OK | MB_ICONEXCLAMATION);
|
||||
}
|
||||
|
||||
void CtrlDisplayListView::onMouseDown(WPARAM wParam, LPARAM lParam, int button)
|
||||
{
|
||||
int y = HIWORD(lParam);
|
||||
@@ -298,6 +309,9 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
|
||||
{
|
||||
if (button == 2)
|
||||
{
|
||||
HMENU menu = GetContextMenu(ContextMenuID::DISPLAYLISTVIEW);
|
||||
EnableMenuItem(menu, ID_GEDBG_SETCOND, GPUBreakpoints::IsAddressBreakpoint(curAddress) ? MF_ENABLED : MF_GRAYED);
|
||||
|
||||
switch (TriggerContextMenu(ContextMenuID::DISPLAYLISTVIEW, wnd, ContextPoint::FromEvent(lParam)))
|
||||
{
|
||||
case ID_DISASM_GOTOINMEMORYVIEW:
|
||||
@@ -308,6 +322,9 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
|
||||
toggleBreakpoint();
|
||||
redraw();
|
||||
break;
|
||||
case ID_GEDBG_SETCOND:
|
||||
PromptBreakpointCond();
|
||||
break;
|
||||
case ID_DISASM_COPYINSTRUCTIONDISASM:
|
||||
{
|
||||
int space = 256 * (selectRangeEnd - selectRangeStart) / instructionSize;
|
||||
|
||||
@@ -30,6 +30,8 @@ class CtrlDisplayListView
|
||||
} pixelPositions;
|
||||
|
||||
void toggleBreakpoint();
|
||||
void PromptBreakpointCond();
|
||||
|
||||
public:
|
||||
CtrlDisplayListView(HWND _wnd);
|
||||
~CtrlDisplayListView();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <windowsx.h>
|
||||
#include "Common/CommonWindows.h"
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
@@ -1114,7 +1114,13 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
bool temp;
|
||||
bool isBreak = IsAddressBreakpoint(pc, temp);
|
||||
if (isBreak && !temp) {
|
||||
RemoveAddressBreakpoint(pc);
|
||||
if (GetAddressBreakpointCond(pc, nullptr)) {
|
||||
int ret = MessageBox(m_hDlg, L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
|
||||
if (ret == IDYES)
|
||||
RemoveAddressBreakpoint(pc);
|
||||
} else {
|
||||
RemoveAddressBreakpoint(pc);
|
||||
}
|
||||
} else {
|
||||
AddAddressBreakpoint(pc);
|
||||
}
|
||||
|
||||
@@ -763,6 +763,7 @@ BEGIN
|
||||
MENUITEM "Jump to Cursor", ID_DISASM_SETPCTOHERE
|
||||
MENUITEM "Set Stall", ID_GEDBG_SETSTALLADDR
|
||||
MENUITEM "Toggle Breakpoint", ID_DISASM_TOGGLEBREAKPOINT
|
||||
MENUITEM "Set Breakpoint Condition", ID_GEDBG_SETCOND
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Go to Displaylist PC", ID_GEDBG_GOTOPC
|
||||
MENUITEM "Go to Address...", ID_GEDBG_GOTOADDR
|
||||
|
||||
@@ -332,6 +332,7 @@
|
||||
#define ID_GEDBG_SHOWONRIGHT 40220
|
||||
#define ID_GEDBG_SHOWONTOPRIGHT 40221
|
||||
#define IDC_GEDBG_STEPVSYNC 40222
|
||||
#define ID_GEDBG_SETCOND 40223
|
||||
|
||||
|
||||
// Dummy option to let the buffered rendering hotkey cycle through all the options.
|
||||
@@ -345,7 +346,7 @@
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 256
|
||||
#define _APS_NEXT_COMMAND_VALUE 40223
|
||||
#define _APS_NEXT_COMMAND_VALUE 40224
|
||||
#define _APS_NEXT_CONTROL_VALUE 1202
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user