Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/CtrlDisAsmView.cpp
3186 views
1
#include "Windows/resource.h"
2
#include "Core/MemMap.h"
3
#include "Windows/W32Util/ContextMenu.h"
4
#include "Windows/W32Util/Misc.h"
5
#include "Windows/W32Util/ShellUtil.h"
6
#include "Windows/MainWindow.h"
7
#include "Windows/InputBox.h"
8
9
#include "Core/MIPS/MIPSAsm.h"
10
#include "Core/MIPS/MIPSAnalyst.h"
11
#include "Core/MIPS/MIPSTables.h"
12
#include "Core/Config.h"
13
#include "Core/Debugger/SymbolMap.h"
14
#include "Core/Reporting.h"
15
#include "Common/StringUtils.h"
16
#include "Windows/Debugger/CtrlDisAsmView.h"
17
#include "Windows/Debugger/DebuggerShared.h"
18
#include "Windows/Debugger/BreakpointWindow.h"
19
#include "Windows/Debugger/EditSymbolsWindow.h"
20
#include "Core/RetroAchievements.h"
21
#include "Windows/main.h"
22
23
#include "Common/CommonWindows.h"
24
#include "Common/Data/Encoding/Utf8.h"
25
#include "Common/System/Display.h"
26
27
#include <tchar.h>
28
#include <set>
29
30
TCHAR CtrlDisAsmView::szClassName[] = _T("CtrlDisAsmView");
31
32
static constexpr UINT_PTR IDT_REDRAW = 0xC0DE0001;
33
static constexpr UINT REDRAW_DELAY = 1000 / 60;
34
35
void CtrlDisAsmView::init()
36
{
37
WNDCLASSEX wc;
38
39
wc.cbSize = sizeof(wc);
40
wc.lpszClassName = szClassName;
41
wc.hInstance = GetModuleHandle(0);
42
wc.lpfnWndProc = CtrlDisAsmView::wndProc;
43
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
44
wc.hIcon = 0;
45
wc.lpszMenuName = 0;
46
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
47
wc.style = 0;
48
wc.cbClsExtra = 0;
49
wc.cbWndExtra = sizeof( CtrlDisAsmView * );
50
wc.hIconSm = 0;
51
52
RegisterClassEx(&wc);
53
}
54
55
void CtrlDisAsmView::deinit()
56
{
57
//UnregisterClass(szClassName, hInst)
58
}
59
60
void CtrlDisAsmView::scanVisibleFunctions()
61
{
62
g_disassemblyManager.analyze(windowStart, g_disassemblyManager.getNthNextAddress(windowStart,visibleRows)-windowStart);
63
}
64
65
LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
66
{
67
CtrlDisAsmView *ccp = CtrlDisAsmView::getFrom(hwnd);
68
static bool lmbDown=false,rmbDown=false;
69
switch(msg)
70
{
71
case WM_NCCREATE:
72
// Allocate a new CustCtrl structure for this window.
73
ccp = new CtrlDisAsmView(hwnd);
74
75
// Continue with window creation.
76
return ccp != NULL;
77
78
// Clean up when the window is destroyed.
79
case WM_NCDESTROY:
80
delete ccp;
81
break;
82
case WM_SETFONT:
83
break;
84
case WM_SIZE:
85
ccp->redraw();
86
break;
87
case WM_PAINT:
88
ccp->onPaint(wParam,lParam);
89
break;
90
case WM_VSCROLL:
91
ccp->onVScroll(wParam,lParam);
92
break;
93
case WM_MOUSEWHEEL:
94
ccp->dontRedraw = false;
95
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
96
{
97
ccp->scrollWindow(-3);
98
} else if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) {
99
ccp->scrollWindow(3);
100
}
101
break;
102
case WM_ERASEBKGND:
103
return FALSE;
104
case WM_KEYDOWN:
105
ccp->onKeyDown(wParam,lParam);
106
return 0;
107
case WM_CHAR:
108
ccp->onChar(wParam,lParam);
109
return 0;
110
case WM_SYSKEYDOWN:
111
ccp->onKeyDown(wParam,lParam);
112
return 0; // return a value so that windows doesn't execute the standard syskey action
113
case WM_KEYUP:
114
ccp->onKeyUp(wParam,lParam);
115
return 0;
116
case WM_LBUTTONDOWN: lmbDown=true; ccp->onMouseDown(wParam,lParam,1); break;
117
case WM_RBUTTONDOWN: rmbDown=true; ccp->onMouseDown(wParam,lParam,2); break;
118
case WM_MOUSEMOVE: ccp->onMouseMove(wParam,lParam,(lmbDown?1:0) | (rmbDown?2:0)); break;
119
case WM_LBUTTONUP: lmbDown=false; ccp->onMouseUp(wParam,lParam,1); break;
120
case WM_RBUTTONUP: rmbDown=false; ccp->onMouseUp(wParam,lParam,2); break;
121
case WM_SETFOCUS:
122
SetFocus(hwnd);
123
ccp->hasFocus=true;
124
ccp->redraw();
125
break;
126
case WM_KILLFOCUS:
127
ccp->hasFocus=false;
128
lmbDown = false;
129
rmbDown = false;
130
ccp->redraw();
131
break;
132
case WM_GETDLGCODE:
133
if (lParam && ((MSG*)lParam)->message == WM_KEYDOWN)
134
{
135
switch (wParam)
136
{
137
case VK_TAB:
138
return DLGC_WANTMESSAGE;
139
default:
140
return DLGC_WANTCHARS|DLGC_WANTARROWS;
141
}
142
}
143
return DLGC_WANTCHARS|DLGC_WANTARROWS;
144
145
case WM_TIMER:
146
if (wParam == IDT_REDRAW) {
147
InvalidateRect(hwnd, nullptr, FALSE);
148
UpdateWindow(hwnd);
149
ccp->redrawScheduled_ = false;
150
KillTimer(hwnd, wParam);
151
}
152
break;
153
154
default:
155
break;
156
}
157
158
return DefWindowProc(hwnd, msg, wParam, lParam);
159
}
160
161
162
CtrlDisAsmView *CtrlDisAsmView::getFrom(HWND hwnd)
163
{
164
return (CtrlDisAsmView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
165
}
166
167
CtrlDisAsmView::CtrlDisAsmView(HWND _wnd)
168
{
169
wnd=_wnd;
170
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this);
171
SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL);
172
SetScrollRange(wnd, SB_VERT, -1, 1, TRUE);
173
174
const float fontScale = 1.0f / g_display.dpi_scale_real_y;
175
charWidth = g_Config.iFontWidth * fontScale;
176
rowHeight = (g_Config.iFontHeight + 2) * fontScale;
177
int scaledFontHeight = g_Config.iFontHeight * fontScale;
178
font = CreateFont(scaledFontHeight, charWidth, 0, 0,
179
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
180
L"Lucida Console");
181
boldfont = CreateFont(scaledFontHeight, charWidth, 0, 0,
182
FW_DEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
183
L"Lucida Console");
184
185
curAddress = 0;
186
showHex = false;
187
hasFocus = false;
188
dontRedraw = false;
189
keyTaken = false;
190
191
matchAddress = -1;
192
searching = false;
193
searchQuery.clear();
194
windowStart = curAddress;
195
whiteBackground = false;
196
displaySymbols = true;
197
calculatePixelPositions();
198
}
199
200
201
CtrlDisAsmView::~CtrlDisAsmView()
202
{
203
DeleteObject(font);
204
DeleteObject(boldfont);
205
g_disassemblyManager.clear();
206
}
207
208
static COLORREF scaleColor(COLORREF color, float factor)
209
{
210
unsigned char r = color & 0xFF;
211
unsigned char g = (color >> 8) & 0xFF;
212
unsigned char b = (color >> 16) & 0xFF;
213
214
r = std::min(255, std::max((int)(r * factor), 0));
215
g = std::min(255, std::max((int)(g * factor), 0));
216
b = std::min(255, std::max((int)(b * factor), 0));
217
218
return (color & 0xFF000000) | (b << 16) | (g << 8) | r;
219
}
220
221
std::string trimString(std::string input)
222
{
223
size_t pos = input.find_first_not_of(" \t");
224
if (pos != 0 && pos != std::string::npos)
225
{
226
input = input.erase(0,pos);
227
}
228
229
pos = input.find_last_not_of(" \t");
230
if (pos != std::string::npos)
231
{
232
size_t size = input.length()-pos-1;
233
input = input.erase(pos+1,size);
234
}
235
236
return input;
237
}
238
239
void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText)
240
{
241
auto memLock = Memory::Lock();
242
if (!Core_IsStepping()) {
243
MessageBox(wnd,L"Cannot change code while the core is running!",L"Error",MB_OK);
244
return;
245
}
246
std::string op;
247
bool result = InputBox_GetString(MainWindow::GetHInstance(), wnd, L"Assemble opcode", defaultText, op, InputBoxFlags::Default);
248
if (!result) {
249
return;
250
}
251
252
// check if it changes registers first
253
auto separator = op.find('=');
254
if (separator != std::string::npos)
255
{
256
std::string registerName = trimString(op.substr(0,separator));
257
std::string expression = trimString(op.substr(separator+1));
258
259
u32 value;
260
if (parseExpression(expression.c_str(),debugger,value) == true)
261
{
262
for (int cat = 0; cat < debugger->GetNumCategories(); cat++)
263
{
264
for (int reg = 0; reg < debugger->GetNumRegsInCategory(cat); reg++)
265
{
266
if (strcasecmp(debugger->GetRegName(cat,reg).c_str(), registerName.c_str()) == 0)
267
{
268
debugger->SetRegValue(cat,reg,value);
269
Reporting::NotifyDebugger();
270
SendMessage(GetParent(wnd),WM_DEB_UPDATE,0,0);
271
return;
272
}
273
}
274
}
275
}
276
277
// try to assemble the input if it failed
278
}
279
280
result = MIPSAsm::MipsAssembleOpcode(op.c_str(), debugger, address);
281
Reporting::NotifyDebugger();
282
if (result == true)
283
{
284
scanVisibleFunctions();
285
286
if (address == curAddress)
287
gotoAddr(g_disassemblyManager.getNthNextAddress(curAddress,1));
288
289
redraw();
290
} else {
291
std::wstring error = ConvertUTF8ToWString(MIPSAsm::GetAssembleError());
292
MessageBox(wnd,error.c_str(),L"Error",MB_OK);
293
}
294
}
295
296
void CtrlDisAsmView::drawBranchLine(HDC hdc, std::map<u32,int> &addressPositions, const BranchLine &line) {
297
HPEN pen;
298
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
299
300
int topY;
301
int bottomY;
302
if (line.first < windowStart)
303
{
304
topY = -1;
305
} else if (line.first >= windowEnd)
306
{
307
topY = rect.bottom+1;
308
} else {
309
topY = addressPositions[line.first] + rowHeight/2;
310
}
311
312
if (line.second < windowStart)
313
{
314
bottomY = -1;
315
} else if (line.second >= windowEnd)
316
{
317
bottomY = rect.bottom+1;
318
} else {
319
bottomY = addressPositions[line.second] + rowHeight/2;
320
}
321
322
if ((topY < 0 && bottomY < 0) || (topY > rect.bottom && bottomY > rect.bottom))
323
{
324
return;
325
}
326
327
// highlight line in a different color if it affects the currently selected opcode
328
if (line.first == curAddress || line.second == curAddress)
329
{
330
pen = CreatePen(0,0,0x257AFA);
331
} else {
332
pen = CreatePen(0,0,0xFF3020);
333
}
334
335
HPEN oldPen = (HPEN) SelectObject(hdc,pen);
336
int x = pixelPositions.arrowsStart+line.laneIndex*8;
337
338
if (topY < 0) // first is not visible, but second is
339
{
340
MoveToEx(hdc,x-2,bottomY,0);
341
LineTo(hdc,x+2,bottomY);
342
LineTo(hdc,x+2,0);
343
344
if (line.type == LINE_DOWN)
345
{
346
MoveToEx(hdc,x,bottomY-4,0);
347
LineTo(hdc,x-4,bottomY);
348
LineTo(hdc,x+1,bottomY+5);
349
}
350
} else if (bottomY > rect.bottom) // second is not visible, but first is
351
{
352
MoveToEx(hdc,x-2,topY,0);
353
LineTo(hdc,x+2,topY);
354
LineTo(hdc,x+2,rect.bottom);
355
356
if (line.type == LINE_UP)
357
{
358
MoveToEx(hdc,x,topY-4,0);
359
LineTo(hdc,x-4,topY);
360
LineTo(hdc,x+1,topY+5);
361
}
362
} else { // both are visible
363
if (line.type == LINE_UP)
364
{
365
MoveToEx(hdc,x-2,bottomY,0);
366
LineTo(hdc,x+2,bottomY);
367
LineTo(hdc,x+2,topY);
368
LineTo(hdc,x-4,topY);
369
370
MoveToEx(hdc,x,topY-4,0);
371
LineTo(hdc,x-4,topY);
372
LineTo(hdc,x+1,topY+5);
373
} else {
374
MoveToEx(hdc,x-2,topY,0);
375
LineTo(hdc,x+2,topY);
376
LineTo(hdc,x+2,bottomY);
377
LineTo(hdc,x-4,bottomY);
378
379
MoveToEx(hdc,x,bottomY-4,0);
380
LineTo(hdc,x-4,bottomY);
381
LineTo(hdc,x+1,bottomY+5);
382
}
383
}
384
385
SelectObject(hdc,oldPen);
386
DeleteObject(pen);
387
}
388
389
std::set<std::string> CtrlDisAsmView::getSelectedLineArguments() {
390
std::set<std::string> args;
391
392
DisassemblyLineInfo line;
393
for (u32 addr = selectRangeStart; addr < selectRangeEnd; addr += 4) {
394
g_disassemblyManager.getLine(addr, displaySymbols, line, debugger);
395
size_t p = 0, nextp = line.params.find(',');
396
while (nextp != line.params.npos) {
397
args.emplace(line.params.substr(p, nextp - p));
398
p = nextp + 1;
399
nextp = line.params.find(',', p);
400
}
401
if (p < line.params.size()) {
402
args.emplace(line.params.substr(p));
403
}
404
}
405
406
return args;
407
}
408
409
void CtrlDisAsmView::drawArguments(HDC hdc, const DisassemblyLineInfo &line, int x, int y, int textColor, const std::set<std::string> &currentArguments) {
410
if (line.params.empty()) {
411
return;
412
}
413
// Don't highlight the selected lines.
414
if (isInInterval(selectRangeStart, selectRangeEnd - selectRangeStart, line.info.opcodeAddress)) {
415
TextOutA(hdc, x, y, line.params.c_str(), (int)line.params.size());
416
return;
417
}
418
419
int highlightedColor = 0xaabb00;
420
if (textColor == 0x0000ff) {
421
highlightedColor = 0xaabb77;
422
}
423
424
UINT prevAlign = SetTextAlign(hdc, TA_UPDATECP);
425
MoveToEx(hdc, x, y, NULL);
426
427
size_t p = 0, nextp = line.params.find(',');
428
while (nextp != line.params.npos) {
429
const std::string arg = line.params.substr(p, nextp - p);
430
if (currentArguments.find(arg) != currentArguments.end() && textColor != 0xffffff) {
431
SetTextColor(hdc, highlightedColor);
432
}
433
TextOutA(hdc, 0, 0, arg.c_str(), (int)arg.size());
434
SetTextColor(hdc,textColor);
435
p = nextp + 1;
436
nextp = line.params.find(',', p);
437
TextOutA(hdc, 0, 0, ",", 1);
438
}
439
if (p < line.params.size()) {
440
const std::string arg = line.params.substr(p);
441
if (currentArguments.find(arg) != currentArguments.end() && textColor != 0xffffff) {
442
SetTextColor(hdc, highlightedColor);
443
}
444
TextOutA(hdc, 0, 0, arg.c_str(), (int)arg.size());
445
SetTextColor(hdc,textColor);
446
}
447
448
SetTextAlign(hdc, prevAlign);
449
}
450
451
void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
452
{
453
auto memLock = Memory::Lock();
454
if (!debugger->isAlive() || Achievements::HardcoreModeActive()) return;
455
456
PAINTSTRUCT ps;
457
HDC actualHdc = BeginPaint(wnd, &ps);
458
HDC hdc = CreateCompatibleDC(actualHdc);
459
HBITMAP hBM = CreateCompatibleBitmap(actualHdc, rect.right-rect.left, rect.bottom-rect.top);
460
SelectObject(hdc, hBM);
461
462
SetBkMode(hdc, TRANSPARENT);
463
464
HPEN nullPen=CreatePen(0,0,0xffffff);
465
HBRUSH nullBrush=CreateSolidBrush(0xffffff);
466
HBRUSH currentBrush=CreateSolidBrush(0xffefe8);
467
468
HPEN oldPen=(HPEN)SelectObject(hdc,nullPen);
469
HBRUSH oldBrush=(HBRUSH)SelectObject(hdc,nullBrush);
470
HFONT oldFont = (HFONT)SelectObject(hdc,(HGDIOBJ)font);
471
HICON breakPoint = (HICON)LoadIcon(GetModuleHandle(0),(LPCWSTR)IDI_STOP);
472
HICON breakPointDisable = (HICON)LoadIcon(GetModuleHandle(0),(LPCWSTR)IDI_STOPDISABLE);
473
474
unsigned int address = windowStart;
475
std::map<u32,int> addressPositions;
476
477
const std::set<std::string> currentArguments = getSelectedLineArguments();
478
DisassemblyLineInfo line;
479
for (int i = 0; i < visibleRows; i++)
480
{
481
g_disassemblyManager.getLine(address,displaySymbols,line, debugger);
482
483
int rowY1 = rowHeight*i;
484
int rowY2 = rowHeight*(i+1);
485
486
addressPositions[address] = rowY1;
487
488
// draw background
489
COLORREF backgroundColor = whiteBackground ? 0xFFFFFF : (debugger->getColor(address, false) & 0xFFFFFF);
490
COLORREF textColor = 0x000000;
491
492
if (isInInterval(address, line.totalSize, debugger->GetPC()))
493
{
494
backgroundColor = scaleColor(backgroundColor,1.05f);
495
}
496
497
if (address >= selectRangeStart && address < selectRangeEnd && searching == false)
498
{
499
if (hasFocus)
500
{
501
backgroundColor = address == curAddress ? 0xFF8822 : 0xFF9933;
502
textColor = 0xFFFFFF;
503
} else {
504
backgroundColor = 0xC0C0C0;
505
}
506
}
507
508
HBRUSH backgroundBrush = CreateSolidBrush(backgroundColor);
509
HPEN backgroundPen = CreatePen(0,0,backgroundColor);
510
SelectObject(hdc,backgroundBrush);
511
SelectObject(hdc,backgroundPen);
512
Rectangle(hdc,0,rowY1,rect.right,rowY1+rowHeight);
513
514
SelectObject(hdc,currentBrush);
515
SelectObject(hdc,nullPen);
516
517
DeleteObject(backgroundBrush);
518
DeleteObject(backgroundPen);
519
520
// display address/symbol
521
bool enabled;
522
if (g_breakpoints.IsAddressBreakPoint(address,&enabled))
523
{
524
if (enabled) textColor = 0x0000FF;
525
int yOffset = std::max(-1, (rowHeight - 14 + 1) / 2);
526
if (!enabled) yOffset++;
527
DrawIconEx(hdc,2,rowY1+1+yOffset,enabled ? breakPoint : breakPointDisable,32,32,0,0,DI_NORMAL);
528
}
529
SetTextColor(hdc,textColor);
530
531
char addressText[64];
532
GetDisasmAddressText(address, addressText, sizeof(addressText), true, line.type == DISTYPE_OPCODE, displaySymbols);
533
TextOutA(hdc, pixelPositions.addressStart, rowY1+2, addressText, (int)strlen(addressText));
534
535
if (isInInterval(address,line.totalSize,debugger->GetPC()))
536
{
537
TextOut(hdc,pixelPositions.opcodeStart-8,rowY1,L"\x25A0",1);
538
}
539
540
// display whether the condition of a branch is met
541
if (line.info.isConditional && address == debugger->GetPC())
542
{
543
line.params += line.info.conditionMet ? " ; true" : " ; false";
544
}
545
546
drawArguments(hdc, line, pixelPositions.argumentsStart, rowY1 + 2, textColor, currentArguments);
547
548
SelectObject(hdc,boldfont);
549
TextOutA(hdc,pixelPositions.opcodeStart,rowY1+2,line.name.c_str(),(int)line.name.size());
550
SelectObject(hdc,font);
551
552
address += line.totalSize;
553
}
554
555
std::vector<BranchLine> branchLines = g_disassemblyManager.getBranchLines(windowStart,address-windowStart);
556
for (size_t i = 0; i < branchLines.size(); i++)
557
{
558
drawBranchLine(hdc,addressPositions,branchLines[i]);
559
}
560
561
SelectObject(hdc,oldFont);
562
SelectObject(hdc,oldPen);
563
SelectObject(hdc,oldBrush);
564
565
// copy bitmap to the actual hdc
566
BitBlt(actualHdc, 0, 0, rect.right, rect.bottom, hdc, 0, 0, SRCCOPY);
567
DeleteObject(hBM);
568
DeleteDC(hdc);
569
570
DeleteObject(nullPen);
571
572
DeleteObject(nullBrush);
573
DeleteObject(currentBrush);
574
575
DestroyIcon(breakPoint);
576
DestroyIcon(breakPointDisable);
577
578
EndPaint(wnd, &ps);
579
}
580
581
582
583
void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
584
{
585
switch (wParam & 0xFFFF)
586
{
587
case SB_LINEDOWN:
588
windowStart = g_disassemblyManager.getNthNextAddress(windowStart,1);
589
break;
590
case SB_LINEUP:
591
windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,1);
592
break;
593
case SB_PAGEDOWN:
594
windowStart = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
595
break;
596
case SB_PAGEUP:
597
windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows);
598
break;
599
default:
600
return;
601
}
602
603
scanVisibleFunctions();
604
redraw();
605
}
606
607
void CtrlDisAsmView::followBranch()
608
{
609
DisassemblyLineInfo line;
610
g_disassemblyManager.getLine(curAddress, true, line, debugger);
611
612
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO)
613
{
614
if (line.info.isBranch)
615
{
616
jumpStack.push_back(curAddress);
617
gotoAddr(line.info.branchTarget);
618
} else if (line.info.hasRelevantAddress)
619
{
620
// well, not exactly a branch, but we can do something anyway
621
SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,line.info.relevantAddress,0);
622
SetFocus(wnd);
623
}
624
} else if (line.type == DISTYPE_DATA)
625
{
626
// jump to the start of the current line
627
SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,curAddress,0);
628
SetFocus(wnd);
629
}
630
}
631
632
void CtrlDisAsmView::onChar(WPARAM wParam, LPARAM lParam)
633
{
634
if (Achievements::HardcoreModeActive())
635
return;
636
637
if (keyTaken) return;
638
639
char str[2];
640
str[0] = wParam;
641
str[1] = 0;
642
assembleOpcode(curAddress,str);
643
}
644
645
646
void CtrlDisAsmView::editBreakpoint()
647
{
648
BreakpointWindow win(wnd,debugger);
649
650
bool exists = false;
651
if (g_breakpoints.IsAddressBreakPoint(curAddress))
652
{
653
auto breakpoints = g_breakpoints.GetBreakpoints();
654
for (size_t i = 0; i < breakpoints.size(); i++)
655
{
656
if (breakpoints[i].addr == curAddress)
657
{
658
win.loadFromBreakpoint(breakpoints[i]);
659
exists = true;
660
break;
661
}
662
}
663
}
664
665
if (!exists)
666
win.initBreakpoint(curAddress);
667
668
if (win.exec())
669
{
670
if (exists)
671
g_breakpoints.RemoveBreakPoint(curAddress);
672
win.addBreakpoint();
673
}
674
}
675
676
void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
677
{
678
if (Achievements::HardcoreModeActive())
679
return;
680
681
dontRedraw = false;
682
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
683
keyTaken = true;
684
685
if (KeyDownAsync(VK_CONTROL))
686
{
687
switch (tolower(wParam & 0xFFFF))
688
{
689
case 'f':
690
case 's':
691
search(false);
692
break;
693
case 'c':
694
case VK_INSERT:
695
CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::DISASM);
696
break;
697
case 'x':
698
disassembleToFile();
699
break;
700
case 'a':
701
assembleOpcode(curAddress,"");
702
break;
703
case 'g':
704
{
705
u32 addr;
706
if (executeExpressionWindow(wnd,debugger,addr) == false) return;
707
gotoAddr(addr);
708
}
709
break;
710
case 'e': // edit breakpoint
711
editBreakpoint();
712
break;
713
case 'd': // toogle breakpoint enabled
714
toggleBreakpoint(true);
715
break;
716
case VK_UP:
717
scrollWindow(-1);
718
scanVisibleFunctions();
719
break;
720
case VK_DOWN:
721
scrollWindow(1);
722
scanVisibleFunctions();
723
break;
724
case VK_NEXT:
725
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT));
726
break;
727
case VK_PRIOR:
728
setCurAddress(windowStart,KeyDownAsync(VK_SHIFT));
729
break;
730
}
731
} else {
732
switch (wParam & 0xFFFF)
733
{
734
case VK_DOWN:
735
setCurAddress(g_disassemblyManager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
736
scrollAddressIntoView();
737
break;
738
case VK_UP:
739
setCurAddress(g_disassemblyManager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
740
scrollAddressIntoView();
741
break;
742
case VK_NEXT:
743
if (g_disassemblyManager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) {
744
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT));
745
scrollAddressIntoView();
746
} else {
747
setCurAddress(g_disassemblyManager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT));
748
scrollAddressIntoView();
749
}
750
break;
751
case VK_PRIOR:
752
if (curAddress != windowStart && curAddressIsVisible()) {
753
setCurAddress(windowStart, KeyDownAsync(VK_SHIFT));
754
scrollAddressIntoView();
755
} else {
756
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT));
757
scrollAddressIntoView();
758
}
759
break;
760
case VK_LEFT:
761
if (jumpStack.empty())
762
{
763
gotoPC();
764
} else {
765
u32 addr = jumpStack[jumpStack.size()-1];
766
jumpStack.pop_back();
767
gotoAddr(addr);
768
}
769
return;
770
case VK_RIGHT:
771
followBranch();
772
return;
773
case VK_TAB:
774
displaySymbols = !displaySymbols;
775
break;
776
case VK_SPACE:
777
debugger->toggleBreakpoint(curAddress);
778
break;
779
case VK_F3:
780
search(true);
781
break;
782
default:
783
keyTaken = false;
784
return;
785
}
786
}
787
redraw();
788
}
789
790
void CtrlDisAsmView::onKeyUp(WPARAM wParam, LPARAM lParam)
791
{
792
793
}
794
795
void CtrlDisAsmView::scrollAddressIntoView()
796
{
797
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
798
799
if (curAddress < windowStart)
800
windowStart = curAddress;
801
else if (curAddress >= windowEnd)
802
windowStart = g_disassemblyManager.getNthPreviousAddress(curAddress,visibleRows-1);
803
804
scanVisibleFunctions();
805
}
806
807
bool CtrlDisAsmView::curAddressIsVisible()
808
{
809
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
810
return curAddress >= windowStart && curAddress < windowEnd;
811
}
812
813
void CtrlDisAsmView::redraw()
814
{
815
if (dontRedraw == true) return;
816
817
GetClientRect(wnd, &rect);
818
visibleRows = rect.bottom/rowHeight;
819
820
if (!redrawScheduled_) {
821
SetTimer(wnd, IDT_REDRAW, REDRAW_DELAY, nullptr);
822
redrawScheduled_ = true;
823
}
824
}
825
826
void CtrlDisAsmView::toggleBreakpoint(bool toggleEnabled)
827
{
828
bool enabled;
829
if (g_breakpoints.IsAddressBreakPoint(curAddress, &enabled)) {
830
if (!enabled) {
831
// enable disabled breakpoints
832
g_breakpoints.ChangeBreakPoint(curAddress, true);
833
} else if (!toggleEnabled && g_breakpoints.GetBreakPointCondition(curAddress) != nullptr) {
834
// don't just delete a breakpoint with a custom condition
835
int ret = MessageBox(wnd,L"This breakpoint has a custom condition.\nDo you want to remove it?",L"Confirmation",MB_YESNO);
836
if (ret == IDYES)
837
g_breakpoints.RemoveBreakPoint(curAddress);
838
} else if (toggleEnabled) {
839
// disable breakpoint
840
g_breakpoints.ChangeBreakPoint(curAddress, false);
841
} else {
842
// otherwise just remove breakpoint
843
g_breakpoints.RemoveBreakPoint(curAddress);
844
}
845
} else {
846
g_breakpoints.AddBreakPoint(curAddress);
847
}
848
}
849
850
void CtrlDisAsmView::onMouseDown(WPARAM wParam, LPARAM lParam, int button)
851
{
852
if (Achievements::HardcoreModeActive())
853
return;
854
dontRedraw = false;
855
int y = HIWORD(lParam);
856
857
u32 newAddress = yToAddress(y);
858
bool extend = KeyDownAsync(VK_SHIFT);
859
if (button == 1)
860
{
861
if (newAddress == curAddress && hasFocus)
862
{
863
toggleBreakpoint();
864
}
865
}
866
else if (button == 2)
867
{
868
// Maintain the current selection if right clicking into it.
869
if (newAddress >= selectRangeStart && newAddress < selectRangeEnd)
870
extend = true;
871
}
872
setCurAddress(newAddress, extend);
873
874
SetFocus(wnd);
875
redraw();
876
}
877
878
void CtrlDisAsmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode) {
879
_assert_msg_((startAddr & 3) == 0, "readMemory() can't handle unaligned reads");
880
881
if (mode != CopyInstructionsMode::DISASM) {
882
int instructionSize = debugger->getInstructionSize(0);
883
int count = (endAddr - startAddr) / instructionSize;
884
int space = count * 32;
885
char *temp = new char[space];
886
887
char *p = temp, *end = temp + space;
888
for (u32 pos = startAddr; pos < endAddr && p < end; pos += instructionSize)
889
{
890
u32 data = mode == CopyInstructionsMode::OPCODES ? debugger->readMemory(pos) : pos;
891
p += snprintf(p, end - p, "%08X", data);
892
893
// Don't leave a trailing newline.
894
if (pos + instructionSize < endAddr && p < end)
895
p += snprintf(p, end - p, "\r\n");
896
}
897
W32Util::CopyTextToClipboard(wnd, temp);
898
delete [] temp;
899
} else {
900
std::string disassembly = DisassembleRange(startAddr,endAddr-startAddr, displaySymbols, debugger);
901
W32Util::CopyTextToClipboard(wnd, disassembly.c_str());
902
}
903
}
904
905
void CtrlDisAsmView::NopInstructions(u32 selectRangeStart, u32 selectRangeEnd) {
906
for (u32 addr = selectRangeStart; addr < selectRangeEnd; addr += 4) {
907
Memory::Write_U32(0, addr);
908
}
909
910
if (currentMIPS) {
911
currentMIPS->InvalidateICache(selectRangeStart, selectRangeEnd - selectRangeStart);
912
}
913
}
914
915
void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
916
{
917
if (Achievements::HardcoreModeActive())
918
return;
919
920
if (button == 1)
921
{
922
int y = HIWORD(lParam);
923
setCurAddress(yToAddress(y), KeyDownAsync(VK_SHIFT));
924
redraw();
925
}
926
else if (button == 2)
927
{
928
// We don't want to let the users play with deallocated or uninitialized debugging objects
929
GlobalUIState state = GetUIState();
930
if (state != UISTATE_INGAME && state != UISTATE_PAUSEMENU) {
931
return;
932
}
933
934
switch (TriggerContextMenu(ContextMenuID::DISASM, wnd, ContextPoint::FromEvent(lParam)))
935
{
936
case ID_DISASM_GOTOINMEMORYVIEW:
937
SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,curAddress,0);
938
break;
939
case ID_DISASM_TOGGLEBREAKPOINT:
940
toggleBreakpoint();
941
redraw();
942
break;
943
case ID_DISASM_ASSEMBLE:
944
assembleOpcode(curAddress,"");
945
break;
946
case ID_DISASM_COPYINSTRUCTIONDISASM:
947
CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::DISASM);
948
break;
949
case ID_DISASM_COPYADDRESS:
950
CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::ADDRESSES);
951
break;
952
case ID_DISASM_COPYINSTRUCTIONHEX:
953
CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::OPCODES);
954
break;
955
case ID_DISASM_NOPINSTRUCTION:
956
NopInstructions(selectRangeStart, selectRangeEnd);
957
redraw();
958
break;
959
case ID_DISASM_EDITSYMBOLS:
960
{
961
EditSymbolsWindow esw(wnd, debugger);
962
if (esw.exec()) {
963
esw.eval();
964
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
965
redraw();
966
}
967
}
968
break;
969
case ID_DISASM_SETPCTOHERE:
970
debugger->SetPC(curAddress);
971
redraw();
972
break;
973
case ID_DISASM_FOLLOWBRANCH:
974
followBranch();
975
break;
976
case ID_DISASM_RUNTOHERE:
977
{
978
SendMessage(GetParent(wnd), WM_COMMAND, ID_DEBUG_RUNTOLINE, 0);
979
redraw();
980
}
981
break;
982
case ID_DISASM_RENAMEFUNCTION:
983
{
984
u32 funcBegin = g_symbolMap->GetFunctionStart(curAddress);
985
if (funcBegin != -1)
986
{
987
char name[256];
988
std::string newname;
989
truncate_cpy(name, g_symbolMap->GetLabelString(funcBegin).c_str());
990
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), L"New function name", name, newname)) {
991
g_symbolMap->SetLabelName(newname.c_str(), funcBegin);
992
u32 funcSize = g_symbolMap->GetFunctionSize(funcBegin);
993
MIPSAnalyst::RegisterFunction(funcBegin, funcSize, newname.c_str());
994
MIPSAnalyst::UpdateHashMap();
995
MIPSAnalyst::ApplyHashMap();
996
SendMessage(GetParent(wnd),WM_DEB_MAPLOADED,0,0);
997
redraw();
998
}
999
}
1000
else
1001
{
1002
MessageBox(MainWindow::GetHWND(), L"No symbol selected",0,0);
1003
}
1004
}
1005
break;
1006
case ID_DISASM_REMOVEFUNCTION:
1007
{
1008
char statusBarTextBuff[256];
1009
u32 funcBegin = g_symbolMap->GetFunctionStart(curAddress);
1010
if (funcBegin != -1)
1011
{
1012
u32 prevBegin = g_symbolMap->GetFunctionStart(funcBegin-1);
1013
if (prevBegin != -1)
1014
{
1015
u32 expandedSize = g_symbolMap->GetFunctionSize(prevBegin) + g_symbolMap->GetFunctionSize(funcBegin);
1016
g_symbolMap->SetFunctionSize(prevBegin,expandedSize);
1017
}
1018
1019
g_symbolMap->RemoveFunction(funcBegin,true);
1020
g_symbolMap->SortSymbols();
1021
g_disassemblyManager.clear();
1022
1023
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
1024
}
1025
else
1026
{
1027
snprintf(statusBarTextBuff,256, "WARNING: unable to find function symbol here");
1028
SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM) statusBarTextBuff);
1029
}
1030
redraw();
1031
}
1032
break;
1033
case ID_DISASM_ADDFUNCTION:
1034
{
1035
char statusBarTextBuff[256];
1036
u32 prevBegin = g_symbolMap->GetFunctionStart(curAddress);
1037
if (prevBegin != -1)
1038
{
1039
if (prevBegin == curAddress)
1040
{
1041
snprintf(statusBarTextBuff,256, "WARNING: There's already a function entry point at this adress");
1042
SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM) statusBarTextBuff);
1043
}
1044
else
1045
{
1046
char symname[128];
1047
u32 prevSize = g_symbolMap->GetFunctionSize(prevBegin);
1048
u32 newSize = curAddress-prevBegin;
1049
g_symbolMap->SetFunctionSize(prevBegin,newSize);
1050
1051
newSize = prevSize-newSize;
1052
snprintf(symname,128,"u_un_%08X",curAddress);
1053
g_symbolMap->AddFunction(symname,curAddress,newSize);
1054
g_symbolMap->SortSymbols();
1055
g_disassemblyManager.clear();
1056
1057
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
1058
}
1059
}
1060
else
1061
{
1062
char symname[128];
1063
int newSize = selectRangeEnd - selectRangeStart;
1064
snprintf(symname, 128, "u_un_%08X", selectRangeStart);
1065
g_symbolMap->AddFunction(symname, selectRangeStart, newSize);
1066
g_symbolMap->SortSymbols();
1067
1068
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
1069
}
1070
redraw();
1071
}
1072
break;
1073
case ID_DISASM_DISASSEMBLETOFILE:
1074
disassembleToFile();
1075
break;
1076
}
1077
return;
1078
}
1079
1080
redraw();
1081
}
1082
1083
void CtrlDisAsmView::onMouseMove(WPARAM wParam, LPARAM lParam, int button)
1084
{
1085
if (Achievements::HardcoreModeActive())
1086
return;
1087
1088
if ((button & 1) != 0)
1089
{
1090
int y = HIWORD(lParam);
1091
setCurAddress(yToAddress(y), KeyDownAsync(VK_SHIFT));
1092
redraw();
1093
}
1094
}
1095
1096
void CtrlDisAsmView::updateStatusBarText()
1097
{
1098
auto memLock = Memory::Lock();
1099
if (!PSP_IsInited())
1100
return;
1101
1102
char text[512];
1103
DisassemblyLineInfo line;
1104
g_disassemblyManager.getLine(curAddress,true,line, debugger);
1105
1106
text[0] = 0;
1107
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO)
1108
{
1109
if (line.info.hasRelevantAddress && IsLikelyStringAt(line.info.relevantAddress)) {
1110
snprintf(text, sizeof(text), "[%08X] = \"%s\"", line.info.relevantAddress, Memory::GetCharPointer(line.info.relevantAddress));
1111
}
1112
1113
if (line.info.isDataAccess) {
1114
if (!Memory::IsValidAddress(line.info.dataAddress)) {
1115
snprintf(text, sizeof(text), "Invalid address %08X",line.info.dataAddress);
1116
} else {
1117
bool isFloat = MIPSGetInfo(line.info.encodedOpcode) & (IS_FPU | IS_VFPU);
1118
switch (line.info.dataSize) {
1119
case 1:
1120
snprintf(text, sizeof(text), "[%08X] = %02X",line.info.dataAddress,Memory::Read_U8(line.info.dataAddress));
1121
break;
1122
case 2:
1123
snprintf(text, sizeof(text), "[%08X] = %04X",line.info.dataAddress,Memory::Read_U16(line.info.dataAddress));
1124
break;
1125
case 4:
1126
{
1127
u32 dataInt = Memory::Read_U32(line.info.dataAddress);
1128
u32 dataFloat = Memory::Read_Float(line.info.dataAddress);
1129
std::string dataString;
1130
if (isFloat)
1131
dataString = StringFromFormat("%08X / %f", dataInt, dataFloat);
1132
else
1133
dataString = StringFromFormat("%08X", dataInt);
1134
1135
const std::string addressSymbol = g_symbolMap->GetLabelString(dataInt);
1136
if (!addressSymbol.empty()) {
1137
snprintf(text, sizeof(text), "[%08X] = %s (%s)", line.info.dataAddress, addressSymbol.c_str(), dataString.c_str());
1138
} else {
1139
snprintf(text, sizeof(text), "[%08X] = %s", line.info.dataAddress, dataString.c_str());
1140
}
1141
break;
1142
}
1143
case 16:
1144
{
1145
uint32_t dataInt[4];
1146
float dataFloat[4];
1147
for (int i = 0; i < 4; ++i) {
1148
dataInt[i] = Memory::Read_U32(line.info.dataAddress + i * 4);
1149
dataFloat[i] = Memory::Read_Float(line.info.dataAddress + i * 4);
1150
}
1151
std::string dataIntString = StringFromFormat("%08X,%08X,%08X,%08X", dataInt[0], dataInt[1], dataInt[2], dataInt[3]);
1152
std::string dataFloatString = StringFromFormat("%f,%f,%f,%f", dataFloat[0], dataFloat[1], dataFloat[2], dataFloat[3]);
1153
1154
snprintf(text, sizeof(text), "[%08X] = %s / %s", line.info.dataAddress, dataIntString.c_str(), dataFloatString.c_str());
1155
break;
1156
}
1157
}
1158
}
1159
}
1160
1161
if (line.info.isBranch)
1162
{
1163
const std::string addressSymbol = g_symbolMap->GetLabelString(line.info.branchTarget);
1164
if (addressSymbol.empty())
1165
{
1166
snprintf(text, sizeof(text), "%08X", line.info.branchTarget);
1167
} else {
1168
snprintf(text, sizeof(text), "%08X = %s",line.info.branchTarget,addressSymbol.c_str());
1169
}
1170
}
1171
} else if (line.type == DISTYPE_DATA) {
1172
u32 start = g_symbolMap->GetDataStart(curAddress);
1173
if (start == -1)
1174
start = curAddress;
1175
1176
u32 diff = curAddress-start;
1177
const std::string label = g_symbolMap->GetLabelString(start);
1178
1179
if (!label.empty()) {
1180
if (diff != 0)
1181
snprintf(text, sizeof(text), "%08X (%s) + %08X",start,label.c_str(),diff);
1182
else
1183
snprintf(text, sizeof(text), "%08X (%s)",start,label.c_str());
1184
} else {
1185
if (diff != 0)
1186
snprintf(text, sizeof(text), "%08X + %08X",start,diff);
1187
else
1188
snprintf(text, sizeof(text), "%08X",start);
1189
}
1190
}
1191
1192
SendMessage(GetParent(wnd),WM_DEB_SETSTATUSBARTEXT,0,(LPARAM)text);
1193
1194
const std::string label = g_symbolMap->GetLabelString(line.info.opcodeAddress);
1195
if (!label.empty()) {
1196
SendMessage(GetParent(wnd),WM_DEB_SETSTATUSBARTEXT,1,(LPARAM)label.c_str());
1197
}
1198
}
1199
1200
u32 CtrlDisAsmView::yToAddress(int y)
1201
{
1202
int line = y/rowHeight;
1203
return g_disassemblyManager.getNthNextAddress(windowStart,line);
1204
}
1205
1206
void CtrlDisAsmView::calculatePixelPositions()
1207
{
1208
pixelPositions.addressStart = 16;
1209
pixelPositions.opcodeStart = pixelPositions.addressStart + 18*charWidth;
1210
pixelPositions.argumentsStart = pixelPositions.opcodeStart + 9*charWidth;
1211
pixelPositions.arrowsStart = pixelPositions.argumentsStart + 30*charWidth;
1212
}
1213
1214
void CtrlDisAsmView::search(bool continueSearch)
1215
{
1216
auto memLock = Memory::Lock();
1217
u32 searchAddress;
1218
1219
if (continueSearch == false || searchQuery[0] == 0)
1220
{
1221
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), L"Search for:", searchQuery, searchQuery) == false
1222
|| searchQuery[0] == 0)
1223
{
1224
SetFocus(wnd);
1225
return;
1226
}
1227
1228
for (size_t i = 0; i < searchQuery.size(); i++)
1229
{
1230
searchQuery[i] = tolower(searchQuery[i]);
1231
}
1232
SetFocus(wnd);
1233
searchAddress = g_disassemblyManager.getNthNextAddress(curAddress,1);
1234
} else {
1235
searchAddress = g_disassemblyManager.getNthNextAddress(matchAddress,1);
1236
}
1237
1238
// limit address to sensible ranges
1239
if (searchAddress < 0x04000000) searchAddress = 0x04000000;
1240
if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
1241
if (searchAddress >= 0x0A000000) {
1242
MessageBox(wnd,L"Not found",L"Search",MB_OK);
1243
return;
1244
}
1245
1246
searching = true;
1247
redraw(); // so the cursor is disabled
1248
1249
DisassemblyLineInfo lineInfo;
1250
while (searchAddress < 0x0A000000)
1251
{
1252
g_disassemblyManager.getLine(searchAddress,displaySymbols,lineInfo, debugger);
1253
1254
char addressText[64];
1255
GetDisasmAddressText(searchAddress, addressText, sizeof(addressText), true, lineInfo.type == DISTYPE_OPCODE, displaySymbols);
1256
1257
const char* opcode = lineInfo.name.c_str();
1258
const char* arguments = lineInfo.params.c_str();
1259
1260
char merged[512];
1261
int mergePos = 0;
1262
1263
// I'm doing it manually to convert everything to lowercase at the same time
1264
for (int i = 0; addressText[i] != 0; i++) merged[mergePos++] = tolower(addressText[i]);
1265
merged[mergePos++] = ' ';
1266
for (int i = 0; opcode[i] != 0; i++) merged[mergePos++] = tolower(opcode[i]);
1267
merged[mergePos++] = ' ';
1268
for (int i = 0; arguments[i] != 0; i++) merged[mergePos++] = tolower(arguments[i]);
1269
merged[mergePos] = 0;
1270
1271
// match!
1272
if (strstr(merged, searchQuery.c_str()) != NULL)
1273
{
1274
matchAddress = searchAddress;
1275
searching = false;
1276
gotoAddr(searchAddress);
1277
return;
1278
}
1279
1280
// cancel search
1281
if ((searchAddress % 256) == 0 && KeyDownAsync(VK_ESCAPE))
1282
{
1283
searching = false;
1284
return;
1285
}
1286
1287
searchAddress = g_disassemblyManager.getNthNextAddress(searchAddress,1);
1288
if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
1289
}
1290
1291
MessageBox(wnd,L"Not found",L"Search",MB_OK);
1292
searching = false;
1293
}
1294
1295
void CtrlDisAsmView::disassembleToFile() {
1296
// get size
1297
u32 size;
1298
if (executeExpressionWindow(wnd,debugger,size) == false)
1299
return;
1300
if (size == 0 || size > 10*1024*1024) {
1301
MessageBox(wnd,L"Invalid size!",L"Error",MB_OK);
1302
return;
1303
}
1304
1305
std::string filename;
1306
if (W32Util::BrowseForFileName(false, nullptr, L"Save Disassembly As...", nullptr, L"All Files\0*.*\0\0", nullptr, filename)) {
1307
std::wstring fileName = ConvertUTF8ToWString(filename);
1308
FILE *output = _wfopen(fileName.c_str(), L"wb");
1309
if (output == nullptr) {
1310
MessageBox(wnd, L"Could not open file!", L"Error", MB_OK);
1311
return;
1312
}
1313
1314
std::string disassembly = DisassembleRange(curAddress, size, displaySymbols, debugger);
1315
fprintf(output, "%s", disassembly.c_str());
1316
1317
fclose(output);
1318
MessageBox(wnd, L"Finished!", L"Done", MB_OK);
1319
}
1320
}
1321
1322
void CtrlDisAsmView::getOpcodeText(u32 address, char* dest, int bufsize)
1323
{
1324
DisassemblyLineInfo line;
1325
address = g_disassemblyManager.getStartAddress(address);
1326
g_disassemblyManager.getLine(address,displaySymbols,line, debugger);
1327
snprintf(dest, bufsize, "%s %s",line.name.c_str(),line.params.c_str());
1328
}
1329
1330
void CtrlDisAsmView::scrollStepping(u32 newPc)
1331
{
1332
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
1333
1334
newPc = g_disassemblyManager.getStartAddress(newPc);
1335
if (newPc >= windowEnd || newPc >= g_disassemblyManager.getNthPreviousAddress(windowEnd,1))
1336
{
1337
windowStart = g_disassemblyManager.getNthPreviousAddress(newPc,visibleRows-2);
1338
}
1339
}
1340
1341
u32 CtrlDisAsmView::getInstructionSizeAt(u32 address)
1342
{
1343
u32 start = g_disassemblyManager.getStartAddress(address);
1344
u32 next = g_disassemblyManager.getNthNextAddress(start,1);
1345
return next - address;
1346
}
1347
1348