CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/BreakpointWindow.cpp
Views: 1401
1
#include <cstdio>
2
3
#include "Common/Data/Encoding/Utf8.h"
4
#include "Common/Math/expression_parser.h"
5
6
#include "BreakpointWindow.h"
7
#include "../resource.h"
8
9
INT_PTR CALLBACK BreakpointWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
10
BreakpointWindow *thiz;
11
if (iMsg == WM_INITDIALOG) {
12
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam);
13
thiz = (BreakpointWindow *)lParam;
14
}
15
else {
16
thiz = (BreakpointWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
17
}
18
19
if (!thiz)
20
return FALSE;
21
return thiz->DlgFunc(hWnd, iMsg, wParam, lParam);
22
}
23
24
INT_PTR BreakpointWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
25
{
26
char str[128];
27
28
switch (iMsg)
29
{
30
case WM_INITDIALOG:
31
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_EXECUTE), BM_SETCHECK, memory ? BST_UNCHECKED : BST_CHECKED, 0);
32
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_MEMORY), BM_SETCHECK, memory ? BST_CHECKED : BST_UNCHECKED, 0);
33
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), BM_SETCHECK, read ? BST_CHECKED : BST_UNCHECKED, 0);
34
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), BM_SETCHECK, write ? BST_CHECKED : BST_UNCHECKED, 0);
35
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), BM_SETCHECK, onChange ? BST_CHECKED : BST_UNCHECKED, 0);
36
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ENABLED), BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, 0);
37
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG), BM_SETCHECK, log ? BST_CHECKED : BST_UNCHECKED, 0);
38
39
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
40
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
41
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
42
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
43
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), log);
44
45
if (address != -1) {
46
snprintf(str, sizeof(str), "0x%08X", address);
47
SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str);
48
}
49
50
snprintf(str, sizeof(str), "0x%08X", size);
51
SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str);
52
53
SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(condition).c_str());
54
SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), ConvertUTF8ToWString(logFormat).c_str());
55
return TRUE;
56
case WM_COMMAND:
57
switch (LOWORD(wParam))
58
{
59
case IDC_BREAKPOINT_EXECUTE:
60
switch (HIWORD(wParam))
61
{
62
case BN_CLICKED:
63
memory = false;
64
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
65
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
66
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
67
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
68
break;
69
}
70
break;
71
case IDC_BREAKPOINT_MEMORY:
72
switch (HIWORD(wParam))
73
{
74
case BN_CLICKED:
75
memory = true;
76
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
77
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
78
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
79
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
80
break;
81
}
82
break;
83
case IDC_BREAKPOINT_LOG:
84
switch (HIWORD(wParam))
85
{
86
case BN_CLICKED:
87
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), GetCheckState(hwnd, IDC_BREAKPOINT_LOG));
88
break;
89
}
90
break;
91
case IDC_BREAKPOINT_OK:
92
switch (HIWORD(wParam))
93
{
94
case BN_CLICKED:
95
if (fetchDialogData(hwnd)) {
96
EndDialog(hwnd, true);
97
}
98
break;
99
};
100
break;
101
case IDC_BREAKPOINT_CANCEL:
102
switch (HIWORD(wParam))
103
{
104
case BN_CLICKED:
105
EndDialog(hwnd, false);
106
break;
107
};
108
break;
109
case IDOK:
110
if (fetchDialogData(hwnd)) {
111
EndDialog(hwnd, true);
112
}
113
break;
114
case IDCANCEL:
115
EndDialog(hwnd, false);
116
break;
117
}
118
}
119
120
return FALSE;
121
}
122
123
bool BreakpointWindow::fetchDialogData(HWND hwnd)
124
{
125
char str[256], errorMessage[512];
126
PostfixExpression exp;
127
128
memory = GetCheckState(hwnd, IDC_BREAKPOINT_MEMORY);
129
read = GetCheckState(hwnd, IDC_BREAKPOINT_READ);
130
write = GetCheckState(hwnd, IDC_BREAKPOINT_WRITE);
131
enabled = GetCheckState(hwnd, IDC_BREAKPOINT_ENABLED);
132
log = GetCheckState(hwnd, IDC_BREAKPOINT_LOG);
133
onChange = GetCheckState(hwnd, IDC_BREAKPOINT_ONCHANGE);
134
135
// parse address
136
GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str, 256);
137
if (cpu->initExpression(str, exp) == false)
138
{
139
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
140
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
141
return false;
142
}
143
144
if (cpu->parseExpression(exp, address) == false)
145
{
146
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
147
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
148
return false;
149
}
150
151
if (memory)
152
{
153
// parse size
154
GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str, 256);
155
if (cpu->initExpression(str, exp) == false)
156
{
157
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
158
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
159
return false;
160
}
161
162
if (cpu->parseExpression(exp, size) == false)
163
{
164
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
165
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
166
return false;
167
}
168
}
169
170
// condition
171
wchar_t tempCond[512];
172
GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), tempCond, 512);
173
condition = ConvertWStringToUTF8(tempCond);
174
compiledCondition.clear();
175
if (!condition.empty())
176
{
177
if (cpu->initExpression(condition.c_str(), compiledCondition) == false)
178
{
179
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", condition.c_str(), getExpressionError());
180
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
181
return false;
182
}
183
}
184
185
wchar_t tempLogFormat[512];
186
GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), tempLogFormat, 512);
187
logFormat = ConvertWStringToUTF8(tempLogFormat);
188
if (!CBreakPoints::ValidateLogFormat(cpu, logFormat)) {
189
snprintf(errorMessage, sizeof(errorMessage), "Invalid log format (example: \"{a1}\").");
190
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
191
return false;
192
}
193
194
return true;
195
}
196
197
bool BreakpointWindow::GetCheckState(HWND hwnd, int dlgItem) {
198
return SendMessage(GetDlgItem(hwnd, dlgItem), BM_GETCHECK, 0, 0) != 0;
199
}
200
201
bool BreakpointWindow::exec() {
202
return DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_BREAKPOINT), parentHwnd, StaticDlgFunc, (LPARAM)this) != 0;
203
}
204
205
void BreakpointWindow::addBreakpoint() {
206
BreakAction result = BREAK_ACTION_IGNORE;
207
if (log)
208
result |= BREAK_ACTION_LOG;
209
if (enabled)
210
result |= BREAK_ACTION_PAUSE;
211
212
if (memory) {
213
// add memcheck
214
int cond = 0;
215
if (read)
216
cond |= MEMCHECK_READ;
217
if (write)
218
cond |= MEMCHECK_WRITE;
219
if (onChange)
220
cond |= MEMCHECK_WRITE_ONCHANGE;
221
222
CBreakPoints::AddMemCheck(address, address + size, (MemCheckCondition)cond, result);
223
224
if (!condition.empty()) {
225
BreakPointCond cond;
226
cond.debug = cpu;
227
cond.expressionString = condition;
228
cond.expression = compiledCondition;
229
CBreakPoints::ChangeMemCheckAddCond(address, address + size, cond);
230
}
231
232
CBreakPoints::ChangeMemCheckLogFormat(address, address + size, logFormat);
233
}
234
else {
235
// add breakpoint
236
CBreakPoints::AddBreakPoint(address, false);
237
238
if (!condition.empty()) {
239
BreakPointCond cond;
240
cond.debug = cpu;
241
cond.expressionString = condition;
242
cond.expression = compiledCondition;
243
CBreakPoints::ChangeBreakPointAddCond(address, cond);
244
}
245
246
CBreakPoints::ChangeBreakPoint(address, result);
247
CBreakPoints::ChangeBreakPointLogFormat(address, logFormat);
248
}
249
}
250
251
void BreakpointWindow::loadFromMemcheck(const MemCheck &memcheck) {
252
memory = true;
253
254
read = (memcheck.cond & MEMCHECK_READ) != 0;
255
write = (memcheck.cond & MEMCHECK_WRITE) != 0;
256
onChange = (memcheck.cond & MEMCHECK_WRITE_ONCHANGE) != 0;
257
258
log = (memcheck.result & BREAK_ACTION_LOG) != 0;
259
enabled = (memcheck.result & BREAK_ACTION_PAUSE) != 0;
260
261
address = memcheck.start;
262
size = memcheck.end - address;
263
264
if (memcheck.hasCondition) {
265
condition = memcheck.condition.expressionString;
266
}
267
else {
268
condition.clear();
269
}
270
271
logFormat = memcheck.logFormat;
272
}
273
274
void BreakpointWindow::loadFromBreakpoint(const BreakPoint& breakpoint) {
275
memory = false;
276
277
log = (breakpoint.result & BREAK_ACTION_LOG) != 0;
278
enabled = (breakpoint.result & BREAK_ACTION_PAUSE) != 0;
279
address = breakpoint.addr;
280
size = 1;
281
282
if (breakpoint.hasCond) {
283
condition = breakpoint.cond.expressionString;
284
}
285
else {
286
condition.clear();
287
}
288
289
logFormat = breakpoint.logFormat;
290
}
291
292
void BreakpointWindow::initBreakpoint(u32 _address) {
293
memory = false;
294
enabled = true;
295
address = _address;
296
size = 1;
297
condition.clear();
298
}
299
300