Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/CtrlRegisterList.cpp
5696 views
1
#include <cmath>
2
3
#include "Common/System/Display.h"
4
#include "Common/Data/Encoding/Utf8.h"
5
#include "Core/Config.h"
6
#include "Core/MemMap.h"
7
#include "Core/Reporting.h"
8
#include "Windows/W32Util/ContextMenu.h"
9
#include "Windows/W32Util/Misc.h"
10
#include "Windows/InputBox.h"
11
#include "Windows/resource.h"
12
13
#include "CtrlRegisterList.h"
14
#include "Debugger_MemoryDlg.h"
15
16
#include "Debugger_Disasm.h"
17
#include "DebuggerShared.h"
18
19
#include "Windows/main.h"
20
21
enum { REGISTER_PC = 32, REGISTER_HI, REGISTER_LO, REGISTERS_END };
22
23
constexpr const wchar_t *szClassName = L"CtrlRegisterList";
24
25
static constexpr UINT_PTR IDT_REDRAW = 0xC0DE0001;
26
static constexpr UINT REDRAW_DELAY = 1000 / 60;
27
28
void CtrlRegisterList::init()
29
{
30
WNDCLASSEX wc;
31
32
wc.cbSize = sizeof(wc);
33
wc.lpszClassName = szClassName;
34
wc.hInstance = GetModuleHandle(0);
35
wc.lpfnWndProc = CtrlRegisterList::wndProc;
36
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
37
wc.hIcon = 0;
38
wc.lpszMenuName = 0;
39
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
40
wc.style = CS_DBLCLKS;
41
wc.cbClsExtra = 0;
42
wc.cbWndExtra = sizeof(CtrlRegisterList *);
43
wc.hIconSm = 0;
44
45
RegisterClassEx(&wc);
46
}
47
48
void CtrlRegisterList::deinit()
49
{
50
//UnregisterClass(szClassName, hInst)
51
}
52
53
LRESULT CALLBACK CtrlRegisterList::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
54
{
55
CtrlRegisterList *ccp = CtrlRegisterList::getFrom(hwnd);
56
static bool lmbDown=false,rmbDown=false;
57
switch(msg)
58
{
59
case WM_NCCREATE:
60
// Allocate a new CustCtrl structure for this window.
61
ccp = new CtrlRegisterList(hwnd);
62
63
// Continue with window creation.
64
return ccp != NULL;
65
66
// Clean up when the window is destroyed.
67
case WM_NCDESTROY:
68
delete ccp;
69
break;
70
case WM_SETFONT:
71
break;
72
case WM_SIZE:
73
ccp->redraw();
74
break;
75
case WM_PAINT:
76
ccp->onPaint(wParam,lParam);
77
break;
78
/*
79
case WM_VSCROLL:
80
ccp->onVScroll(wParam,lParam);
81
break;*/
82
case WM_ERASEBKGND:
83
return FALSE;
84
case WM_KEYDOWN:
85
ccp->onKeyDown(wParam,lParam);
86
return 0;
87
case WM_KEYUP:
88
if (wParam == VK_CONTROL) ccp->ctrlDown = false;
89
return 0;
90
case WM_LBUTTONDOWN: SetFocus(hwnd); lmbDown=true; ccp->onMouseDown(wParam,lParam,1); break;
91
case WM_RBUTTONDOWN: rmbDown=true; ccp->onMouseDown(wParam,lParam,2); break;
92
case WM_MOUSEMOVE: ccp->onMouseMove(wParam,lParam,(lmbDown?1:0) | (rmbDown?2:0)); break;
93
case WM_LBUTTONUP: lmbDown=false; ccp->onMouseUp(wParam,lParam,1); break;
94
case WM_RBUTTONUP: rmbDown=false; ccp->onMouseUp(wParam,lParam,2); break;
95
case WM_LBUTTONDBLCLK: ccp->editRegisterValue(); break;
96
case WM_SETFOCUS:
97
SetFocus(hwnd);
98
ccp->hasFocus=true;
99
ccp->redraw();
100
break;
101
case WM_KILLFOCUS:
102
ccp->hasFocus=false;
103
ccp->redraw();
104
break;
105
case WM_GETDLGCODE: // want chars so that we can return 0 on key press and supress the beeping sound
106
return DLGC_WANTARROWS|DLGC_WANTCHARS;
107
108
case WM_TIMER:
109
if (wParam == IDT_REDRAW) {
110
InvalidateRect(hwnd, nullptr, FALSE);
111
UpdateWindow(hwnd);
112
ccp->redrawScheduled_ = false;
113
KillTimer(hwnd, wParam);
114
}
115
break;
116
117
default:
118
break;
119
}
120
121
return DefWindowProc(hwnd, msg, wParam, lParam);
122
}
123
124
CtrlRegisterList *CtrlRegisterList::getFrom(HWND hwnd)
125
{
126
return (CtrlRegisterList *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
127
}
128
129
CtrlRegisterList::CtrlRegisterList(HWND _wnd)
130
: wnd(_wnd) {
131
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this);
132
133
const float fontScale = 1.0f / g_display.dpi_scale_real_y;
134
rowHeight = g_Config.iFontHeight * fontScale;
135
int charWidth = g_Config.iFontWidth * fontScale;
136
font = CreateFont(rowHeight, charWidth, 0, 0,
137
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
138
L"Lucida Console");
139
}
140
141
CtrlRegisterList::~CtrlRegisterList()
142
{
143
DeleteObject(font);
144
delete [] lastCat0Values;
145
delete [] changedCat0Regs;
146
}
147
148
void fillRect(HDC hdc, RECT *rect, COLORREF colour);
149
150
151
152
//Yeah this truly turned into a mess with the latest additions.. but it sure looks nice ;)
153
void CtrlRegisterList::onPaint(WPARAM wParam, LPARAM lParam)
154
{
155
if (!cpu)
156
return;
157
158
GetClientRect(wnd, &rect);
159
PAINTSTRUCT ps;
160
HDC hdc;
161
162
hdc = BeginPaint(wnd, &ps);
163
// TODO: Add any drawing code here...
164
int width = rect.right;
165
//numRows=(numRows&(~1)) + 1;
166
SetBkMode(hdc, TRANSPARENT);
167
DWORD bgColor = 0xffffff;
168
HPEN nullPen=CreatePen(0,0,bgColor);
169
HPEN currentPen=CreatePen(0,0,0);
170
HPEN selPen=CreatePen(0,0,0x808080);
171
172
LOGBRUSH lbr;
173
lbr.lbHatch=0; lbr.lbStyle=0;
174
lbr.lbColor=bgColor;
175
HBRUSH nullBrush=CreateBrushIndirect(&lbr);
176
lbr.lbColor=0xFFEfE8;
177
HBRUSH currentBrush=CreateBrushIndirect(&lbr);
178
lbr.lbColor=0x70FF70;
179
HBRUSH pcBrush=CreateBrushIndirect(&lbr);
180
181
HPEN oldPen=(HPEN)SelectObject(hdc,nullPen);
182
HBRUSH oldBrush=(HBRUSH)SelectObject(hdc,nullBrush);
183
184
185
HFONT oldFont = (HFONT)SelectObject(hdc,(HGDIOBJ)font);
186
// HICON breakPoint = (HICON)LoadIcon(GetModuleHandle(0),(LPCSTR)IDI_STOP);
187
// HICON breakPointDisable = (HICON)LoadIcon(GetModuleHandle(0),(LPCSTR)IDI_STOPDISABLE);
188
189
int nc = cpu->GetNumCategories();
190
for (int i=0; i<nc; i++)
191
{
192
SelectObject(hdc,i==category?currentPen:nullPen);
193
SelectObject(hdc,i==category?pcBrush:nullBrush);
194
Rectangle(hdc,width*i/nc,0,width*(i+1)/nc,rowHeight);
195
const char *name = cpu->GetCategoryName(i);
196
TextOutA(hdc,width*i/nc,1,name,(int)strlen(name));
197
}
198
199
int numRows=rect.bottom/rowHeight;
200
201
for (int i=0; i<numRows; i++)
202
{
203
int rowY1 = rowHeight*(i+1);
204
int rowY2 = rowHeight*(i+2);
205
206
207
lbr.lbColor = i==selection?0xffeee0:0xffffff;
208
209
SelectObject(hdc,currentBrush);
210
SelectObject(hdc,nullPen);
211
Rectangle(hdc,0,rowY1,16,rowY2);
212
213
if (selecting && i == selection)
214
SelectObject(hdc,selPen);
215
else
216
SelectObject(hdc,nullPen);
217
218
HBRUSH mojsBrush=CreateBrushIndirect(&lbr);
219
SelectObject(hdc,mojsBrush);
220
221
//else
222
// SelectObject(hdc,i==0 ? currentBrush : nullBrush);
223
224
Rectangle(hdc,16,rowY1,width,rowY2);
225
226
// Check for any changes in the registers.
227
if (lastPC != cpu->GetPC())
228
{
229
for (int j = 0, n = cpu->GetNumRegsInCategory(0); j < n; ++j)
230
{
231
u32 v = cpu->GetRegValue(0, j);
232
changedCat0Regs[j] = v != lastCat0Values[j];
233
lastCat0Values[j] = v;
234
}
235
236
changedCat0Regs[REGISTER_PC] = cpu->GetPC() != lastCat0Values[REGISTER_PC];
237
lastCat0Values[REGISTER_PC] = cpu->GetPC();
238
changedCat0Regs[REGISTER_HI] = cpu->GetHi() != lastCat0Values[REGISTER_HI];
239
lastCat0Values[REGISTER_HI] = cpu->GetHi();
240
changedCat0Regs[REGISTER_LO] = cpu->GetLo() != lastCat0Values[REGISTER_LO];
241
lastCat0Values[REGISTER_LO] = cpu->GetLo();
242
243
lastPC = cpu->GetPC();
244
}
245
246
SelectObject(hdc,currentBrush);
247
DeleteObject(mojsBrush);
248
if (i<cpu->GetNumRegsInCategory(category))
249
{
250
char temp[256];
251
int temp_len = snprintf(temp, sizeof(temp), "%s", cpu->GetRegName(category, i).c_str());
252
SetTextColor(hdc,0x600000);
253
TextOutA(hdc,17,rowY1,temp,temp_len);
254
SetTextColor(hdc,0x000000);
255
256
cpu->PrintRegValue(category, i, temp, sizeof(temp));
257
if (category == 0 && changedCat0Regs[i])
258
SetTextColor(hdc, 0x0000FF);
259
else
260
SetTextColor(hdc,0x004000);
261
TextOutA(hdc,77,rowY1,temp,(int)strlen(temp));
262
} else if (category == 0 && i < REGISTERS_END)
263
{
264
char temp[256];
265
int len;
266
u32 value = -1;
267
268
switch (i)
269
{
270
case REGISTER_PC:
271
value = cpu->GetPC();
272
len = snprintf(temp, sizeof(temp), "pc");
273
break;
274
case REGISTER_HI:
275
value = cpu->GetHi();
276
len = snprintf(temp, sizeof(temp), "hi");
277
break;
278
case REGISTER_LO:
279
value = cpu->GetLo();
280
len = snprintf(temp, sizeof(temp), "lo");
281
break;
282
default:
283
temp[0] = '\0';
284
len = 0;
285
break;
286
}
287
288
SetTextColor(hdc,0x600000);
289
TextOutA(hdc,17,rowY1,temp,len);
290
len = snprintf(temp, sizeof(temp), "%08X",value);
291
if (changedCat0Regs[i])
292
SetTextColor(hdc, 0x0000FF);
293
else
294
SetTextColor(hdc,0x004000);
295
TextOutA(hdc,77,rowY1,temp,(int)strlen(temp));
296
}
297
}
298
299
SelectObject(hdc,oldFont);
300
SelectObject(hdc,oldPen);
301
SelectObject(hdc,oldBrush);
302
303
DeleteObject(nullPen);
304
DeleteObject(currentPen);
305
DeleteObject(selPen);
306
307
DeleteObject(nullBrush);
308
DeleteObject(pcBrush);
309
DeleteObject(currentBrush);
310
311
// DestroyIcon(breakPoint);
312
// DestroyIcon(breakPointDisable);
313
314
EndPaint(wnd, &ps);
315
}
316
317
318
319
void CtrlRegisterList::onKeyDown(WPARAM wParam, LPARAM lParam)
320
{
321
RECT rect;
322
GetClientRect(this->wnd, &rect);
323
324
if (ctrlDown && tolower(wParam) == 'c')
325
{
326
copyRegisterValue();
327
return;
328
}
329
330
switch (wParam & 0xFFFF)
331
{
332
case VK_DOWN:
333
selection++;
334
break;
335
case VK_UP:
336
selection--;
337
break;
338
case VK_NEXT:
339
selection+=4;
340
break;
341
case VK_PRIOR:
342
selection-=4;
343
break;
344
case VK_CONTROL:
345
ctrlDown = true;
346
break;
347
default:
348
return;
349
}
350
redraw();
351
}
352
353
354
void CtrlRegisterList::redraw() {
355
if (!redrawScheduled_) {
356
SetTimer(wnd, IDT_REDRAW, REDRAW_DELAY, nullptr);
357
redrawScheduled_ = true;
358
}
359
}
360
361
u32 CtrlRegisterList::getSelectedRegValue(char *out, size_t size)
362
{
363
int reg = selection;
364
u32 val;
365
366
if (selection >= cpu->GetNumRegsInCategory(category))
367
{
368
if (category != 0 || selection >= REGISTERS_END)
369
{
370
*out = '\0';
371
return -1;
372
}
373
374
switch (selection)
375
{
376
case REGISTER_PC:
377
val = cpu->GetPC();
378
break;
379
case REGISTER_HI:
380
val = cpu->GetHi();
381
break;
382
case REGISTER_LO:
383
val = cpu->GetLo();
384
break;
385
default:
386
*out = '\0';
387
return -1;
388
}
389
}
390
else
391
val = cpu->GetRegValue(category, reg);
392
393
snprintf(out, size, "%08X", val);
394
return val;
395
}
396
397
void CtrlRegisterList::copyRegisterValue()
398
{
399
if (!Core_IsStepping())
400
{
401
MessageBox(wnd,L"Can't copy register values while the core is running.",L"Error",MB_OK);
402
return;
403
}
404
405
char temp[24];
406
getSelectedRegValue(temp, 24);
407
W32Util::CopyTextToClipboard(wnd, temp);
408
}
409
410
void CtrlRegisterList::editRegisterValue()
411
{
412
if (!Core_IsStepping())
413
{
414
MessageBox(wnd,L"Can't change registers while the core is running.",L"Error",MB_OK);
415
return;
416
}
417
418
char temp[24];
419
u32 val = getSelectedRegValue(temp, 24);
420
int reg = selection;
421
422
std::string value = temp;
423
if (InputBox_GetString(GetModuleHandle(NULL),wnd,L"Set new value",value,value)) {
424
if (parseExpression(value.c_str(),cpu,val) == false) {
425
displayExpressionError(wnd);
426
} else {
427
switch (reg)
428
{
429
case REGISTER_PC:
430
cpu->SetPC(val);
431
break;
432
case REGISTER_HI:
433
cpu->SetHi(val);
434
break;
435
case REGISTER_LO:
436
cpu->SetLo(val);
437
break;
438
default:
439
cpu->SetRegValue(category, reg, val);
440
break;
441
}
442
Reporting::NotifyDebugger();
443
redraw();
444
SendMessage(GetParent(wnd),WM_DEB_UPDATE,0,0); // registers changed -> disassembly needs to be updated
445
}
446
}
447
}
448
449
void CtrlRegisterList::onMouseDown(WPARAM wParam, LPARAM lParam, int button)
450
{
451
int x = (s16)LOWORD(lParam);
452
int y = (s16)HIWORD(lParam);
453
if (x>16)
454
{
455
oldSelection=selection;
456
457
if (y>rowHeight)
458
{
459
selection=yToIndex(y);
460
SetCapture(wnd);
461
bool oldselecting=selecting;
462
selecting=true;
463
if (!oldselecting || (selection!=oldSelection))
464
redraw();
465
}
466
else
467
{
468
RECT rc;
469
SetCapture(wnd);
470
GetWindowRect(wnd,&rc);
471
int lastCat = category;
472
category = (x*cpu->GetNumCategories())/(rc.right-rc.left);
473
if (category<0) category=0;
474
if (category>=cpu->GetNumCategories())
475
category=cpu->GetNumCategories()-1;
476
if (category!=lastCat)
477
redraw();
478
}
479
}
480
else
481
{
482
redraw();
483
}
484
}
485
486
void CtrlRegisterList::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
487
{
488
int x = LOWORD(lParam);
489
int y = HIWORD(lParam);
490
491
if (button==2 && x>16)
492
{
493
//popup menu?
494
int cat = category;
495
int reg = selection;
496
u32 val;
497
if (selection < cpu->GetNumRegsInCategory(cat))
498
{
499
val = cpu->GetRegValue(cat, reg);
500
}
501
else if (cat == 0 && selection < REGISTERS_END)
502
{
503
switch (selection)
504
{
505
case REGISTER_PC:
506
val = cpu->GetPC();
507
break;
508
case REGISTER_HI:
509
val = cpu->GetHi();
510
break;
511
case REGISTER_LO:
512
val = cpu->GetLo();
513
break;
514
default:
515
return;
516
}
517
}
518
else
519
{
520
return;
521
}
522
523
switch (TriggerContextMenu(ContextMenuID::REGLIST, wnd, ContextPoint::FromEvent(lParam)))
524
{
525
case ID_REGLIST_GOTOINMEMORYVIEW:
526
SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,val,0);
527
break;
528
case ID_REGLIST_GOTOINDISASM:
529
if (disasmWindow)
530
disasmWindow->Goto(val);
531
break;
532
case ID_REGLIST_COPYVALUE:
533
copyRegisterValue();
534
break;
535
case ID_REGLIST_CHANGE:
536
editRegisterValue();
537
break;
538
}
539
return;
540
}
541
if (x>16)
542
{
543
selection=yToIndex(y);
544
selecting=false;
545
ReleaseCapture();
546
redraw();
547
}
548
}
549
550
void CtrlRegisterList::onMouseMove(WPARAM wParam, LPARAM lParam, int button)
551
{
552
if (button&1)
553
{
554
int x = LOWORD(lParam);
555
int y = (signed short)HIWORD(lParam);
556
// if (x>16)
557
{
558
/*
559
if (y<0)
560
{
561
curAddress-=align;
562
redraw();
563
}
564
else if (y>rect.bottom)
565
{
566
curAddress+=align;
567
redraw();
568
}
569
else*/
570
onMouseDown(wParam,lParam,1);
571
}
572
}
573
}
574
575
576
int CtrlRegisterList::yToIndex(int y)
577
{
578
// int ydiff=y-rect.bottom/2-rowHeight_/2;
579
// ydiff=(int)(floorf((float)ydiff / (float)rowHeight_))+1;
580
// return curAddress + ydiff * align;
581
int n = (y/rowHeight) - 1;
582
if (n<0) n=0;
583
return n;
584
}
585
586