Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/Debugger_Disasm.cpp
3186 views
1
#include "Core/Config.h"
2
#include "Core/MemMap.h"
3
#include "Windows/resource.h"
4
#include "Windows/InputBox.h"
5
6
#include "Core/Debugger/Breakpoints.h"
7
#include "Core/Debugger/SymbolMap.h"
8
#include "Core/RetroAchievements.h"
9
#include "Windows/Debugger/BreakpointWindow.h"
10
#include "Windows/Debugger/CtrlDisAsmView.h"
11
#include "Windows/Debugger/Debugger_MemoryDlg.h"
12
#include "Windows/Debugger/Debugger_Disasm.h"
13
#include "Windows/Debugger/Debugger_VFPUDlg.h"
14
#include "Windows/Debugger/DebuggerShared.h"
15
// #include "Windows/W32Util/DarkMode.h"
16
17
#include "Windows/main.h"
18
#include "Windows/Debugger/CtrlRegisterList.h"
19
#include "Windows/Debugger/CtrlMemView.h"
20
#include "Windows/Debugger/Debugger_Lists.h"
21
#include "Windows/MainWindow.h"
22
23
#include "Core/Core.h"
24
#include "Core/HLE/HLE.h"
25
#include "Core/CoreTiming.h"
26
#include "Core/MIPS/MIPSAnalyst.h"
27
28
#include "Common/Data/Encoding/Utf8.h"
29
30
#include "Common/CommonWindows.h"
31
#include "Common/StringUtils.h"
32
33
#include <windowsx.h>
34
#include <commctrl.h>
35
36
static FAR WNDPROC DefGotoEditProc;
37
38
LRESULT CALLBACK GotoEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
39
{
40
switch(message)
41
{
42
case WM_KEYDOWN:
43
if( wParam == VK_RETURN )
44
{
45
SendMessage(GetParent(hDlg),WM_DEB_GOTOADDRESSEDIT,0,0);
46
return 0;
47
}
48
break;
49
case WM_KEYUP:
50
if( wParam == VK_RETURN ) return 0;
51
break;
52
case WM_CHAR:
53
if( wParam == VK_RETURN ) return 0;
54
break;
55
case WM_GETDLGCODE:
56
if (lParam && ((MSG*)lParam)->message == WM_KEYDOWN)
57
{
58
if (wParam == VK_RETURN) return DLGC_WANTMESSAGE;
59
}
60
break;
61
};
62
63
return (LRESULT)CallWindowProc((WNDPROC)DefGotoEditProc,hDlg,message,wParam,lParam);
64
}
65
66
static FAR WNDPROC DefFuncListProc;
67
68
LRESULT CALLBACK FuncListProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
69
{
70
switch(message)
71
{
72
case WM_KEYDOWN:
73
if( wParam == VK_RETURN )
74
{
75
SendMessage(GetParent(hDlg),WM_COMMAND,MAKEWPARAM(IDC_FUNCTIONLIST,CBN_DBLCLK),0);
76
SetFocus(hDlg); // it's more natural to keep the focus when using keyboard controls
77
return 0;
78
}
79
break;
80
case WM_GETDLGCODE:
81
if (lParam && ((MSG*)lParam)->message == WM_KEYDOWN)
82
{
83
if (wParam == VK_RETURN) return DLGC_WANTMESSAGE;
84
}
85
break;
86
};
87
88
return (LRESULT)CallWindowProc((WNDPROC)DefFuncListProc,hDlg,message,wParam,lParam);
89
}
90
91
static constexpr UINT_PTR IDT_UPDATE = 0xC0DE0042;
92
static constexpr UINT UPDATE_DELAY = 1000 / 60;
93
94
CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, MIPSDebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent) {
95
cpu = _cpu;
96
lastTicks_ = PSP_IsInited() ? CoreTiming::GetTicks() : 0;
97
breakpoints_ = &g_breakpoints;
98
99
SetWindowText(m_hDlg, L"R4");
100
101
RECT windowRect;
102
GetWindowRect(m_hDlg,&windowRect);
103
int defaultWidth = windowRect.right-windowRect.left;
104
int defaultHeight = windowRect.bottom-windowRect.top;
105
minWidth = defaultWidth - 100;
106
minHeight = defaultHeight - 200;
107
108
int x = g_Config.iDisasmWindowX == -1 ? windowRect.left : g_Config.iDisasmWindowX;
109
int y = g_Config.iDisasmWindowY == -1 ? windowRect.top : g_Config.iDisasmWindowY;
110
int w = g_Config.iDisasmWindowW == -1 ? defaultWidth : g_Config.iDisasmWindowW;
111
int h = g_Config.iDisasmWindowH == -1 ? defaultHeight : g_Config.iDisasmWindowH;
112
113
// init status bar
114
statusBarWnd = CreateWindowEx(0, STATUSCLASSNAME, L"", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, m_hDlg, (HMENU)IDC_DISASMSTATUSBAR, _hInstance, NULL);
115
if (g_Config.bDisplayStatusBar == false) {
116
ShowWindow(statusBarWnd,SW_HIDE);
117
}
118
119
// set it to use two parts
120
RECT statusBarRect;
121
GetClientRect(statusBarWnd,&statusBarRect);
122
123
int parts[2];
124
parts[1] = statusBarRect.right-statusBarRect.left;
125
parts[0] = parts[1]*2./3.;
126
127
SendMessage(statusBarWnd, SB_SETPARTS, (WPARAM) 2, (LPARAM) parts);
128
129
// init other controls
130
CtrlDisAsmView *ptr = DisAsmView();
131
ptr->setDebugger(cpu);
132
ptr->gotoAddr(0x00000000);
133
134
CtrlRegisterList *rl = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST));
135
rl->setCPU(cpu);
136
137
leftTabs = new TabControl(GetDlgItem(m_hDlg,IDC_LEFTTABS));
138
leftTabs->SetIgnoreBottomMargin(true);
139
leftTabs->AddTab(GetDlgItem(m_hDlg,IDC_REGLIST),L"Regs");
140
leftTabs->AddTab(GetDlgItem(m_hDlg,IDC_FUNCTIONLIST),L"Funcs");
141
leftTabs->ShowTab(0);
142
143
// subclass the goto edit box
144
HWND editWnd = GetDlgItem(m_hDlg,IDC_ADDRESS);
145
DefGotoEditProc = (WNDPROC)GetWindowLongPtr(editWnd,GWLP_WNDPROC);
146
SetWindowLongPtr(editWnd,GWLP_WNDPROC,(LONG_PTR)GotoEditProc);
147
148
// subclass the function list
149
HWND funcListWnd = GetDlgItem(m_hDlg,IDC_FUNCTIONLIST);
150
DefFuncListProc = (WNDPROC)GetWindowLongPtr(funcListWnd,GWLP_WNDPROC);
151
SetWindowLongPtr(funcListWnd,GWLP_WNDPROC,(LONG_PTR)FuncListProc);
152
153
// init bottom tabs
154
bottomTabs = new TabControl(GetDlgItem(m_hDlg,IDC_DEBUG_BOTTOMTABS));
155
156
HWND memHandle = GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW);
157
CtrlMemView *mem = CtrlMemView::getFrom(memHandle);
158
mem->setDebugger(_cpu);
159
bottomTabs->AddTab(memHandle,L"Memory");
160
161
breakpointList = new CtrlBreakpointList(GetDlgItem(m_hDlg,IDC_BREAKPOINTLIST),cpu,ptr);
162
breakpointList->reloadBreakpoints();
163
bottomTabs->AddTab(breakpointList->GetHandle(),L"Breakpoints");
164
165
threadList = new CtrlThreadList(GetDlgItem(m_hDlg,IDC_THREADLIST));
166
threadList->reloadThreads();
167
bottomTabs->AddTab(threadList->GetHandle(),L"Threads");
168
169
stackTraceView = new CtrlStackTraceView(GetDlgItem(m_hDlg,IDC_STACKFRAMES),cpu,ptr);
170
stackTraceView->loadStackTrace();
171
bottomTabs->AddTab(stackTraceView->GetHandle(),L"Stack frames");
172
173
moduleList = new CtrlModuleList(GetDlgItem(m_hDlg,IDC_MODULELIST),cpu);
174
moduleList->loadModules();
175
bottomTabs->AddTab(moduleList->GetHandle(),L"Modules");
176
177
watchList_ = new CtrlWatchList(GetDlgItem(m_hDlg, IDC_WATCHLIST), cpu);
178
bottomTabs->AddTab(watchList_->GetHandle(), L"Watch");
179
180
bottomTabs->SetShowTabTitles(g_Config.bShowBottomTabTitles);
181
bottomTabs->ShowTab(memHandle);
182
183
// Actually resize the window to the proper size (after the above setup.)
184
// do it twice so that the window definitely receives a WM_SIZE message with
185
// the correct size (the default from the .rc tends to be off)
186
MoveWindow(m_hDlg,x,y,1,1,FALSE);
187
MoveWindow(m_hDlg,x,y,w,h,TRUE);
188
SetDebugMode(true, true);
189
}
190
191
CDisasm::~CDisasm()
192
{
193
DestroyWindow(statusBarWnd);
194
195
delete leftTabs;
196
delete bottomTabs;
197
delete breakpointList;
198
delete threadList;
199
delete stackTraceView;
200
delete moduleList;
201
}
202
203
void CDisasm::step(CPUStepType stepType) {
204
if (!PSP_IsInited() || !Core_IsStepping()) {
205
return;
206
}
207
208
CtrlDisAsmView *ptr = DisAsmView();
209
ptr->setDontRedraw(true);
210
lastTicks_ = CoreTiming::GetTicks();
211
212
u32 stepSize = ptr->getInstructionSizeAt(cpu->GetPC());
213
Core_RequestCPUStep(stepType, stepSize);
214
}
215
216
void CDisasm::runToLine() {
217
if (!PSP_IsInited()) {
218
return;
219
}
220
221
CtrlDisAsmView *ptr = DisAsmView();
222
u32 pos = ptr->getSelection();
223
224
lastTicks_ = CoreTiming::GetTicks();
225
ptr->setDontRedraw(true);
226
breakpoints_->AddBreakPoint(pos,true);
227
Core_Resume();
228
}
229
230
BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
231
switch(message) {
232
case WM_INITDIALOG:
233
// DarkModeInitDialog(m_hDlg);
234
return TRUE;
235
236
case WM_NOTIFY:
237
switch (wParam) {
238
case IDC_LEFTTABS:
239
leftTabs->HandleNotify(lParam);
240
break;
241
case IDC_BREAKPOINTLIST:
242
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, breakpointList->HandleNotify(lParam));
243
return TRUE;
244
case IDC_THREADLIST:
245
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, threadList->HandleNotify(lParam));
246
return TRUE;
247
case IDC_STACKFRAMES:
248
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, stackTraceView->HandleNotify(lParam));
249
return TRUE;
250
case IDC_MODULELIST:
251
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, moduleList->HandleNotify(lParam));
252
return TRUE;
253
case IDC_WATCHLIST:
254
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, watchList_->HandleNotify(lParam));
255
return TRUE;
256
case IDC_DEBUG_BOTTOMTABS:
257
bottomTabs->HandleNotify(lParam);
258
break;
259
}
260
break;
261
case WM_COMMAND:
262
{
263
if (Achievements::HardcoreModeActive())
264
return TRUE;
265
266
CtrlDisAsmView *ptr = DisAsmView();
267
switch (LOWORD(wParam)) {
268
case ID_TOGGLE_BREAK:
269
SendMessage(MainWindow::GetHWND(), WM_COMMAND, ID_TOGGLE_BREAK, 0);
270
break;
271
272
case ID_DEBUG_DISPLAYMEMVIEW:
273
bottomTabs->ShowTab(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW));
274
break;
275
276
case ID_DEBUG_DISPLAYBREAKPOINTLIST:
277
bottomTabs->ShowTab(breakpointList->GetHandle());
278
break;
279
280
case ID_DEBUG_DISPLAYTHREADLIST:
281
bottomTabs->ShowTab(threadList->GetHandle());
282
break;
283
284
case ID_DEBUG_DISPLAYSTACKFRAMELIST:
285
bottomTabs->ShowTab(stackTraceView->GetHandle());
286
break;
287
288
case ID_DEBUG_DISPLAYREGISTERLIST:
289
leftTabs->ShowTab(0);
290
break;
291
292
case ID_DEBUG_DISPLAYFUNCTIONLIST:
293
leftTabs->ShowTab(1);
294
break;
295
296
case ID_DEBUG_ADDBREAKPOINT:
297
{
298
CtrlDisAsmView *view = DisAsmView();
299
keepStatusBarText = true;
300
view->LockPosition();
301
bool isRunning = Core_IsActive();
302
if (isRunning) {
303
Core_Break(BreakReason::AddBreakpoint, 0);
304
Core_WaitInactive();
305
}
306
307
BreakpointWindow bpw(m_hDlg,cpu);
308
if (bpw.exec()) bpw.addBreakpoint();
309
310
if (isRunning)
311
Core_Resume();
312
view->UnlockPosition();
313
keepStatusBarText = false;
314
}
315
break;
316
317
case ID_DEBUG_STEPOVER:
318
if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) step(CPUStepType::Over);
319
break;
320
321
case ID_DEBUG_STEPINTO:
322
if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) step(CPUStepType::Into);
323
break;
324
325
case ID_DEBUG_RUNTOLINE:
326
if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) runToLine();
327
break;
328
329
case ID_DEBUG_STEPOUT:
330
if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) step(CPUStepType::Out);
331
break;
332
333
case ID_DEBUG_HIDEBOTTOMTABS:
334
{
335
RECT rect;
336
hideBottomTabs = !hideBottomTabs;
337
GetClientRect(m_hDlg,&rect);
338
UpdateSize(rect.right-rect.left,rect.bottom-rect.top);
339
}
340
break;
341
342
case ID_DEBUG_TOGGLEBOTTOMTABTITLES:
343
bottomTabs->SetShowTabTitles(!bottomTabs->GetShowTabTitles());
344
break;
345
346
case IDC_SHOWVFPU:
347
MainWindow::CreateVFPUWindow();
348
vfpudlg->Show(true);
349
break;
350
351
case IDC_FUNCTIONLIST:
352
switch (HIWORD(wParam))
353
{
354
case CBN_DBLCLK:
355
{
356
HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam));
357
int n = ListBox_GetCurSel(lb);
358
if (n!=-1)
359
{
360
unsigned int addr = (unsigned int)ListBox_GetItemData(lb,n);
361
ptr->gotoAddr(addr);
362
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
363
}
364
}
365
break;
366
case CBN_SELCHANGE:
367
{
368
HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam));
369
int n = ListBox_GetCurSel(lb);
370
371
wchar_t buffer[512];
372
ListBox_GetText(lb,n,buffer);
373
SendMessage(statusBarWnd,SB_SETTEXT,1,(LPARAM) buffer);
374
}
375
};
376
break;
377
378
case IDC_GOTOINT:
379
switch (HIWORD(wParam))
380
{
381
case LBN_SELCHANGE:
382
{
383
HWND lb =GetDlgItem(m_hDlg,LOWORD(wParam));
384
int n = ComboBox_GetCurSel(lb);
385
unsigned int addr = (unsigned int)ComboBox_GetItemData(lb,n);
386
if (addr != 0xFFFFFFFF)
387
{
388
ptr->gotoAddr(addr);
389
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
390
}
391
}
392
break;
393
};
394
break;
395
396
case IDC_STOPGO:
397
{
398
if (!PSP_IsInited()) {
399
break;
400
}
401
if (!Core_IsStepping()) { // stop
402
ptr->setDontRedraw(false);
403
Core_Break(BreakReason::DebugBreak, 0);
404
} else { // go
405
lastTicks_ = CoreTiming::GetTicks();
406
Core_Resume();
407
}
408
}
409
break;
410
411
case IDC_STEP:
412
step(CPUStepType::Into);
413
break;
414
415
case IDC_STEPOVER:
416
step(CPUStepType::Over);
417
break;
418
419
case IDC_STEPOUT:
420
step(CPUStepType::Out);
421
break;
422
423
case IDC_STEPHLE:
424
{
425
if (Core_IsActive())
426
break;
427
lastTicks_ = CoreTiming::GetTicks();
428
429
hleDebugBreak();
430
Core_Resume();
431
}
432
break;
433
434
case IDC_MEMCHECK:
435
SendMessage(m_hDlg,WM_COMMAND,ID_DEBUG_ADDBREAKPOINT,0);
436
break;
437
438
case IDC_GOTOPC:
439
{
440
ptr->gotoPC();
441
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
442
UpdateDialog();
443
}
444
break;
445
case IDC_GOTORA:
446
{
447
ptr->gotoAddr(cpu->GetRA());
448
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
449
}
450
break;
451
452
default:
453
return FALSE;
454
}
455
return TRUE;
456
}
457
458
case WM_DEB_MAPLOADED:
459
NotifyMapLoaded();
460
break;
461
462
case WM_DEB_GOTOWPARAM:
463
{
464
CtrlDisAsmView *ptr = DisAsmView();
465
ptr->gotoAddr(wParam);
466
SetFocus(GetDlgItem(m_hDlg,IDC_DISASMVIEW));
467
break;
468
}
469
case WM_DEB_GOTOADDRESSEDIT:
470
{
471
if (!PSP_IsInited()) {
472
break;
473
}
474
wchar_t szBuffer[256];
475
CtrlDisAsmView *ptr = DisAsmView();
476
GetWindowText(GetDlgItem(m_hDlg,IDC_ADDRESS),szBuffer,256);
477
478
u32 addr;
479
if (parseExpression(ConvertWStringToUTF8(szBuffer).c_str(),cpu,addr) == false)
480
{
481
displayExpressionError(GetDlgItem(m_hDlg,IDC_ADDRESS));
482
} else {
483
ptr->gotoAddr(addr);
484
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
485
}
486
UpdateDialog();
487
}
488
break;
489
490
case WM_DEB_SETDEBUGLPARAM:
491
SetDebugMode(lParam != 0, true);
492
return TRUE;
493
494
case WM_DEB_UPDATE:
495
Update();
496
return TRUE;
497
498
case WM_DEB_AFTERSTEP:
499
{
500
CtrlDisAsmView *ptr = DisAsmView();
501
// At this point, the step should be done, and the new address is just PC.
502
// Ideally, this part should be done as a reaction to an update message and not directly here.
503
// That way we could get rid of the sleep.
504
u32 oldAddress = ptr->getSelection();
505
u32 newAddress = cpu->GetPC();
506
if (newAddress > oldAddress && newAddress < oldAddress + 12) {
507
// Heuristic for when to scroll at the edge rather than jump the window.
508
ptr->scrollStepping(newAddress);
509
}
510
ptr->gotoAddr(newAddress);
511
Update();
512
break;
513
}
514
515
case WM_DEB_TABPRESSED:
516
bottomTabs->NextTab(true);
517
SetFocus(bottomTabs->CurrentTabHandle());
518
break;
519
520
case WM_DEB_SETSTATUSBARTEXT:
521
if (!keepStatusBarText)
522
{
523
if (wParam == 0)
524
{
525
// erase the second part if the first is set
526
SendMessage(statusBarWnd,SB_SETTEXT,0,(LPARAM)ConvertUTF8ToWString((const char *)lParam).c_str());
527
SendMessage(statusBarWnd,SB_SETTEXT,1,(LPARAM)L"");
528
} else if (wParam == 1)
529
{
530
SendMessage(statusBarWnd,SB_SETTEXT,1,(LPARAM)ConvertUTF8ToWString((const char *)lParam).c_str());
531
}
532
}
533
break;
534
case WM_DEB_GOTOHEXEDIT:
535
{
536
CtrlMemView *memory = CtrlMemView::getFrom(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW));
537
memory->gotoAddr(wParam);
538
539
// display the memory viewer too
540
bottomTabs->ShowTab(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW));
541
}
542
break;
543
case WM_SIZE:
544
{
545
UpdateSize(LOWORD(lParam), HIWORD(lParam));
546
SendMessage(statusBarWnd,WM_SIZE,0,10);
547
SavePosition();
548
return TRUE;
549
}
550
551
case WM_MOVE:
552
SavePosition();
553
break;
554
case WM_GETMINMAXINFO:
555
{
556
MINMAXINFO *m = (MINMAXINFO *)lParam;
557
// Reduce the minimum size slightly, so they can size it however they like.
558
m->ptMinTrackSize.x = minWidth;
559
//m->ptMaxTrackSize.x = m->ptMinTrackSize.x;
560
m->ptMinTrackSize.y = minHeight;
561
}
562
return TRUE;
563
case WM_CLOSE:
564
Show(false);
565
return TRUE;
566
case WM_ACTIVATE:
567
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
568
g_activeWindow = WINDOW_CPUDEBUGGER;
569
} else {
570
g_activeWindow = WINDOW_OTHER;
571
}
572
break;
573
574
case WM_TIMER:
575
if (wParam == IDT_UPDATE) {
576
ProcessUpdateDialog();
577
updateDialogScheduled_ = false;
578
KillTimer(GetDlgHandle(), wParam);
579
580
if (Achievements::HardcoreModeActive()) {
581
SendMessage(m_hDlg, WM_CLOSE, 0, 0);
582
}
583
}
584
break;
585
}
586
return 0; // DarkModeDlgProc(m_hDlg, message, wParam, lParam);
587
}
588
589
void CDisasm::updateThreadLabel(bool clear)
590
{
591
char label[512];
592
if (clear) {
593
snprintf(label, sizeof(label), "Thread: -");
594
} else {
595
snprintf(label, sizeof(label), "Thread: %s", threadList->getCurrentThreadName());
596
}
597
598
SetDlgItemText(m_hDlg, IDC_THREADNAME, ConvertUTF8ToWString(label).c_str());
599
}
600
601
void CDisasm::UpdateSize(WORD width, WORD height)
602
{
603
struct Position
604
{
605
int x,y;
606
int w,h;
607
};
608
609
RECT windowRect;
610
Position positions[3];
611
612
HWND disasm = GetDlgItem(m_hDlg, IDC_DISASMVIEW);
613
HWND leftTabs = GetDlgItem(m_hDlg,IDC_LEFTTABS);
614
HWND bottomTabs = GetDlgItem(m_hDlg, IDC_DEBUG_BOTTOMTABS);
615
616
// ignore the status bar
617
int topHeightOffset = 0;
618
if (g_Config.bDisplayStatusBar)
619
{
620
GetWindowRect(statusBarWnd,&windowRect);
621
topHeightOffset = (windowRect.bottom-windowRect.top);
622
}
623
624
CtrlDisAsmView *ptr = DisAsmView();
625
int disassemblyRowHeight = ptr->getRowHeight();
626
627
// disassembly
628
GetWindowRect(disasm,&windowRect);
629
MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&windowRect,2);
630
positions[0].x = windowRect.left;
631
positions[0].y = windowRect.top;
632
633
// compute border height of the disassembly
634
int totalHeight = windowRect.bottom-windowRect.top;
635
GetClientRect(disasm,&windowRect);
636
int clientHeight = windowRect.bottom-windowRect.top;
637
int borderHeight = totalHeight-clientHeight;
638
639
// left tabs
640
GetWindowRect(leftTabs,&windowRect);
641
MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&windowRect,2);
642
positions[1].x = windowRect.left;
643
positions[1].y = windowRect.top;
644
positions[1].w = positions[0].x-2*windowRect.left;
645
int borderMargin = positions[1].x;
646
647
float weight = hideBottomTabs ? 1.f : 390.f/500.f;
648
649
// don't use the part above the disassembly for the computations
650
int bottomHeightOffset = positions[0].y;
651
positions[0].w = width-borderMargin-positions[0].x;
652
positions[0].h = (height-bottomHeightOffset-topHeightOffset) * weight;
653
positions[0].h = ((positions[0].h-borderHeight)/disassemblyRowHeight)*disassemblyRowHeight+borderHeight;
654
positions[1].h = positions[0].h-(positions[1].y-positions[0].y);
655
656
// bottom tabs
657
positions[2].x = borderMargin;
658
positions[2].y = positions[0].y+positions[0].h+borderMargin;
659
positions[2].w = width-2*borderMargin;
660
positions[2].h = hideBottomTabs ? 0 : height-bottomHeightOffset-positions[2].y;
661
662
// now actually move all the windows
663
MoveWindow(disasm,positions[0].x,positions[0].y,positions[0].w,positions[0].h,TRUE);
664
MoveWindow(leftTabs,positions[1].x,positions[1].y,positions[1].w,positions[1].h,TRUE);
665
MoveWindow(bottomTabs,positions[2].x,positions[2].y,positions[2].w,positions[2].h,TRUE);
666
ShowWindow(bottomTabs,hideBottomTabs ? SW_HIDE : SW_NORMAL);
667
}
668
669
void CDisasm::SavePosition()
670
{
671
RECT rc;
672
if (GetWindowRect(m_hDlg, &rc))
673
{
674
g_Config.iDisasmWindowX = rc.left;
675
g_Config.iDisasmWindowY = rc.top;
676
g_Config.iDisasmWindowW = rc.right - rc.left;
677
g_Config.iDisasmWindowH = rc.bottom - rc.top;
678
}
679
}
680
681
void CDisasm::SetDebugMode(bool _bDebug, bool switchPC)
682
{
683
HWND hDlg = m_hDlg;
684
bool ingame = (GetUIState() == UISTATE_INGAME || GetUIState() == UISTATE_EXCEPTION) && PSP_IsInited();
685
686
// If we're stepping, update debugging windows.
687
// This is called potentially asynchronously, so state might've changed.
688
if (Core_IsStepping() && ingame) {
689
breakpointList->reloadBreakpoints();
690
threadList->reloadThreads();
691
stackTraceView->loadStackTrace();
692
moduleList->loadModules();
693
watchList_->RefreshValues();
694
695
EnableWindow(GetDlgItem(hDlg, IDC_STOPGO), TRUE);
696
EnableWindow(GetDlgItem(hDlg, IDC_STEP), TRUE);
697
EnableWindow(GetDlgItem(hDlg, IDC_STEPOVER), TRUE);
698
EnableWindow(GetDlgItem(hDlg, IDC_STEPHLE), TRUE);
699
EnableWindow(GetDlgItem(hDlg, IDC_STEPOUT), TRUE);
700
EnableWindow(GetDlgItem(hDlg, IDC_GOTOPC), TRUE);
701
EnableWindow(GetDlgItem(hDlg, IDC_GOTORA), TRUE);
702
CtrlDisAsmView *ptr = DisAsmView();
703
ptr->setDontRedraw(false);
704
if (switchPC)
705
ptr->gotoPC();
706
707
ptr->scanVisibleFunctions();
708
}
709
else
710
{
711
if (ingame)
712
EnableWindow(GetDlgItem(hDlg, IDC_STOPGO), TRUE);
713
else
714
EnableWindow(GetDlgItem(hDlg, IDC_STOPGO), FALSE);
715
EnableWindow(GetDlgItem(hDlg, IDC_STEP), FALSE);
716
EnableWindow(GetDlgItem(hDlg, IDC_STEPOVER), FALSE);
717
EnableWindow(GetDlgItem(hDlg, IDC_STEPHLE), FALSE);
718
EnableWindow(GetDlgItem(hDlg, IDC_STEPOUT), FALSE);
719
EnableWindow(GetDlgItem(hDlg, IDC_GOTOPC), FALSE);
720
EnableWindow(GetDlgItem(hDlg, IDC_GOTORA), FALSE);
721
CtrlRegisterList *reglist = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST));
722
reglist->redraw();
723
}
724
725
UpdateDialog();
726
}
727
728
void CDisasm::Show(bool bShow, bool includeToTop) {
729
if (deferredSymbolFill_ && bShow) {
730
if (g_symbolMap) {
731
g_symbolMap->FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), ST_FUNCTION);
732
deferredSymbolFill_ = false;
733
}
734
}
735
Dialog::Show(bShow, includeToTop);
736
}
737
738
void CDisasm::NotifyMapLoaded() {
739
if (m_bShowState != SW_HIDE && g_symbolMap) {
740
g_symbolMap->FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), ST_FUNCTION);
741
} else {
742
deferredSymbolFill_ = true;
743
}
744
CtrlDisAsmView *ptr = DisAsmView();
745
ptr->clearFunctions();
746
ptr->redraw();
747
}
748
749
void CDisasm::Goto(u32 addr)
750
{
751
CtrlDisAsmView *ptr = DisAsmView();
752
ptr->gotoAddr(addr);
753
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
754
ptr->redraw();
755
}
756
757
void CDisasm::UpdateDialog() {
758
if (!updateDialogScheduled_) {
759
SetTimer(GetDlgHandle(), IDT_UPDATE, UPDATE_DELAY, nullptr);
760
updateDialogScheduled_ = true;
761
}
762
763
// Since these update on a delay, it's okay to do them immediately.
764
CtrlDisAsmView *ptr = DisAsmView();
765
ptr->redraw();
766
CtrlRegisterList *rl = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg, IDC_REGLIST));
767
rl->redraw();
768
769
// Repaint windows at the bottom. only the memory view needs to be forced to redraw.
770
// All others are updated manually
771
CtrlMemView *memview = CtrlMemView::getFrom(GetDlgItem(m_hDlg, IDC_DEBUGMEMVIEW));
772
memview->redraw();
773
774
// Update memory window too.
775
if (memoryWindow)
776
memoryWindow->Update();
777
if (vfpudlg)
778
vfpudlg->Update();
779
}
780
781
void CDisasm::ProcessUpdateDialog() {
782
/*
783
HWND gotoInt = GetDlgItem(m_hDlg, IDC_GOTOINT);
784
ComboBox_ResetContent(gotoInt);
785
for (int i=0; i<numRegions; i++)
786
{
787
// TODO: wchar_t
788
int n = ComboBox_AddString(gotoInt,regions[i].name);
789
ComboBox_SetItemData(gotoInt,n,regions[i].start);
790
}
791
ComboBox_InsertString(gotoInt,0,"[Goto Rgn]");
792
ComboBox_SetItemData(gotoInt,0,0xFFFFFFFF);
793
ComboBox_SetCurSel(gotoInt,0);
794
*/
795
796
// Update Debug Counter
797
if (PSP_IsInited()) {
798
wchar_t tempTicks[24]{};
799
_snwprintf(tempTicks, 23, L"%lld", CoreTiming::GetTicks() - lastTicks_);
800
SetDlgItemText(m_hDlg, IDC_DEBUG_COUNT, tempTicks);
801
}
802
803
bool ingame = (GetUIState() == UISTATE_INGAME || GetUIState() == UISTATE_EXCEPTION) && PSP_IsInited();
804
if (Core_IsStepping() || !ingame) {
805
SetDlgItemText(m_hDlg, IDC_STOPGO, L"Go");
806
} else {
807
SetDlgItemText(m_hDlg, IDC_STOPGO, L"Break");
808
}
809
810
updateThreadLabel(!ingame || !Core_IsStepping());
811
}
812
813
CtrlDisAsmView *CDisasm::DisAsmView() {
814
return CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
815
}
816
817