From 85a071568c7875c80cd08ddf1ddd86cd31642707 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Apr 2023 00:35:37 -0700 Subject: [PATCH] Debugger: Allow adding/removing watches. --- CMakeLists.txt | 3 +- Windows/Debugger/Debugger_Lists.cpp | 31 +++++++- Windows/Debugger/WatchItemWindow.cpp | 103 +++++++++++++++++++++++++++ Windows/Debugger/WatchItemWindow.h | 53 ++++++++++++++ Windows/PPSSPP.vcxproj | 2 + Windows/PPSSPP.vcxproj.filters | 6 ++ Windows/ppsspp.rc | 13 ++++ Windows/resource.h | 3 +- 8 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 Windows/Debugger/WatchItemWindow.cpp create mode 100644 Windows/Debugger/WatchItemWindow.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ecd57949b..79f75233a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2302,7 +2302,8 @@ set(WindowsFiles Windows/Debugger/Debugger_SymbolMap.h Windows/Debugger/Debugger_VFPUDlg.cpp Windows/Debugger/Debugger_VFPUDlg.h - Windows/Debugger/SimpleELF.h + Windows/Debugger/WatchItemWindow.cpp + Windows/Debugger/WatchItemWindow.h Windows/GEDebugger/CtrlDisplayListView.cpp Windows/GEDebugger/SimpleGLWindow.cpp Windows/GEDebugger/TabState.cpp diff --git a/Windows/Debugger/Debugger_Lists.cpp b/Windows/Debugger/Debugger_Lists.cpp index 1f763883b2..92ff4ec457 100644 --- a/Windows/Debugger/Debugger_Lists.cpp +++ b/Windows/Debugger/Debugger_Lists.cpp @@ -3,8 +3,9 @@ #include #include #include "Windows/Debugger/BreakpointWindow.h" -#include "Windows/Debugger/DebuggerShared.h" #include "Windows/Debugger/CtrlDisAsmView.h" +#include "Windows/Debugger/DebuggerShared.h" +#include "Windows/Debugger/WatchItemWindow.h" #include "Windows/W32Util/ContextMenu.h" #include "Windows/MainWindow.h" #include "Windows/resource.h" @@ -902,11 +903,39 @@ void CtrlWatchList::OnRightClick(int itemIndex, int column, const POINT &pt) { } void CtrlWatchList::AddWatch() { + WatchItemWindow win(nullptr, GetHandle(), cpu_); + if (win.Exec()) { + WatchInfo info; + if (cpu_->initExpression(win.GetExpression().c_str(), info.expression)) { + info.name = win.GetName(); + info.originalExpression = win.GetExpression(); + watches_.push_back(info); + Update(); + } else { + char errorMessage[512]; + snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", win.GetExpression().c_str(), getExpressionError()); + MessageBoxA(GetHandle(), errorMessage, "Error", MB_OK); + } + } } void CtrlWatchList::EditWatch(int pos) { + WatchItemWindow win(nullptr, GetHandle(), cpu_); + win.Init(watches_[pos].name, watches_[pos].originalExpression); + if (win.Exec()) { + if (cpu_->initExpression(win.GetExpression().c_str(), watches_[pos].expression)) { + watches_[pos].name = win.GetName(); + watches_[pos].originalExpression = win.GetExpression(); + Update(); + } else { + char errorMessage[512]; + snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", win.GetExpression().c_str(), getExpressionError()); + MessageBoxA(GetHandle(), errorMessage, "Error", MB_OK); + } + } } void CtrlWatchList::DeleteWatch(int pos) { watches_.erase(watches_.begin() + pos); + Update(); } diff --git a/Windows/Debugger/WatchItemWindow.cpp b/Windows/Debugger/WatchItemWindow.cpp new file mode 100644 index 0000000000..bf127f0508 --- /dev/null +++ b/Windows/Debugger/WatchItemWindow.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2023- 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 "Common/Common.h" +#include "Common/Data/Encoding/Utf8.h" +#include "Windows/Debugger/WatchItemWindow.h" +#include "Windows/resource.h" + +INT_PTR CALLBACK WatchItemWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { + WatchItemWindow *thiz; + if (iMsg == WM_INITDIALOG) { + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam); + thiz = (WatchItemWindow *)lParam; + } else { + thiz = (WatchItemWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + } + + if (!thiz) + return FALSE; + return thiz->DlgFunc(hWnd, iMsg, wParam, lParam); +} + +INT_PTR WatchItemWindow::DlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { + switch (iMsg) { + case WM_INITDIALOG: + SetWindowTextW(GetDlgItem(hWnd, IDC_BREAKPOINT_ADDRESS), ConvertUTF8ToWString(name_).c_str()); + SetWindowTextW(GetDlgItem(hWnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(expression_).c_str()); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_BREAKPOINT_OK: + switch (HIWORD(wParam)) { + case BN_CLICKED: + if (FetchDialogData(hWnd)) { + EndDialog(hWnd, true); + return TRUE; + } + break; + }; + break; + case IDC_BREAKPOINT_CANCEL: + switch (HIWORD(wParam)) { + case BN_CLICKED: + EndDialog(hWnd, false); + return TRUE; + }; + break; + case IDOK: + if (FetchDialogData(hWnd)) { + EndDialog(hWnd, true); + return TRUE; + } + break; + case IDCANCEL: + EndDialog(hWnd, false); + return TRUE; + } + break; + + default: + break; + } + + return FALSE; +} + +bool WatchItemWindow::Exec() { + return DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_CPUWATCH), parentHwnd_, StaticDlgFunc, (LPARAM)this) != 0; +} + +bool WatchItemWindow::FetchDialogData(HWND hwnd) { + wchar_t textValue[512]; + + GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), textValue, ARRAY_SIZE(textValue)); + name_ = ConvertWStringToUTF8(textValue); + + GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), textValue, ARRAY_SIZE(textValue)); + expression_ = ConvertWStringToUTF8(textValue); + PostfixExpression compiled; + if (!cpu_->initExpression(expression_.c_str(), compiled)) { + char errorMessage[512]; + snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", expression_.c_str(), getExpressionError()); + MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + return false; + } + + return true; +} diff --git a/Windows/Debugger/WatchItemWindow.h b/Windows/Debugger/WatchItemWindow.h new file mode 100644 index 0000000000..6ae7b2305e --- /dev/null +++ b/Windows/Debugger/WatchItemWindow.h @@ -0,0 +1,53 @@ +// Copyright (c) 2023- 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 +#include "Common/CommonWindows.h" +#include "Common/CommonTypes.h" +#include "Core/Debugger/DebugInterface.h" + +class WatchItemWindow { +public: + WatchItemWindow(HINSTANCE inst, HWND parent, DebugInterface *cpu) : parentHwnd_(parent), cpu_(cpu) {} + + void Init(const std::string &name, const std::string &expression) { + name_ = name; + expression_ = expression; + } + + bool Exec(); + + const std::string &GetName() const { + return name_; + } + const std::string &GetExpression() const { + return expression_; + } + +private: + static INT_PTR CALLBACK StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + INT_PTR DlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + bool FetchDialogData(HWND hwnd); + + HWND parentHwnd_; + DebugInterface *cpu_; + + std::string name_; + std::string expression_; +}; diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index c99a146bd5..885b399624 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -832,6 +832,7 @@ true + @@ -1385,6 +1386,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index f45f9253c4..b3195e189a 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -274,6 +274,9 @@ Windows\W32Util + + Windows\Debugger + @@ -559,6 +562,9 @@ Windows\W32Util + + Windows\Debugger + diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 51a0e43788..11d0929b6f 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -389,6 +389,19 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,173,79,50,14 END +IDD_CPUWATCH DIALOGEX 0, 0, 236, 70 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Watch" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Name",IDC_STATIC,7,9,36,8 + EDITTEXT IDC_BREAKPOINT_ADDRESS,56,7,173,14,ES_AUTOHSCROLL + LTEXT "Expression",IDC_STATIC,7,28,36,8 + EDITTEXT IDC_BREAKPOINT_CONDITION,56,26,173,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDC_BREAKPOINT_OK,144,47,41,14 + PUSHBUTTON "Cancel",IDC_BREAKPOINT_CANCEL,186,47,42,14 +END + ///////////////////////////////////////////////////////////////////////////// // diff --git a/Windows/resource.h b/Windows/resource.h index 9736173a88..07ccb7cc8d 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -59,6 +59,7 @@ #define IDD_GEDBG_TAB_VERTICES 254 #define IDD_GEDBG_TAB_MATRICES 255 #define IDD_GEDBG_STEPCOUNT 256 +#define IDD_CPUWATCH 257 #define IDC_STOPGO 1001 #define IDC_ADDRESS 1002 @@ -349,7 +350,7 @@ // Next default values for new objects #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 256 +#define _APS_NEXT_RESOURCE_VALUE 258 #define _APS_NEXT_COMMAND_VALUE 40231 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101