1 // NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
2 
3 #pragma once
4 
5 //////////////////////////////////////////////////////////////////////////
6 //CtrlDisAsmView
7 // CtrlDisAsmView.cpp
8 //////////////////////////////////////////////////////////////////////////
9 //This Win32 control is made to be flexible and usable with
10 //every kind of CPU architechture that has fixed width instruction words.
11 //Just supply it an instance of a class derived from Debugger, with all methods
12 //overridden for full functionality. Look at the ppc one for an example.
13 //
14 //To add to a dialog box, just draw a User Control in the dialog editor,
15 //and set classname to "CtrlDisAsmView". you also need to call CtrlDisAsmView::init()
16 //before opening this dialog, to register the window class.
17 //
18 //To get a class instance to be able to access it, just use
19 //  CtrlDisAsmView::getFrom(GetDlgItem(yourdialog, IDC_yourid)).
20 
21 #include "../../Core/Debugger/DebugInterface.h"
22 #include "../../Core/Debugger/DisassemblyManager.h"
23 
24 
25 #include "Common/CommonWindows.h"
26 #include <vector>
27 #include <algorithm>
28 
29 using std::min;
30 using std::max;
31 
32 class CtrlDisAsmView
33 {
34 	HWND wnd;
35 	HFONT font;
36 	HFONT boldfont;
37 	RECT rect;
38 
39 	DisassemblyManager manager;
40 	u32 curAddress;
41 	u32 selectRangeStart;
42 	u32 selectRangeEnd;
43 	int rowHeight;
44 	int charWidth;
45 
46 	bool hasFocus;
47 	bool showHex;
48 	DebugInterface *debugger;
49 	static TCHAR szClassName[];
50 
51 	u32 windowStart;
52 	int visibleRows;
53 	bool whiteBackground;
54 	bool displaySymbols;
55 
56 	struct {
57 		int addressStart;
58 		int opcodeStart;
59 		int argumentsStart;
60 		int arrowsStart;
61 	} pixelPositions;
62 
63 	std::vector<u32> jumpStack;
64 
65 	std::string searchQuery;
66 	int matchAddress;
67 	bool searching;
68 	bool dontRedraw;
69 	bool keyTaken;
70 
71 	void assembleOpcode(u32 address, std::string defaultText);
72 	std::string disassembleRange(u32 start, u32 size);
73 	void disassembleToFile();
74 	void search(bool continueSearch);
75 	void followBranch();
76 	void calculatePixelPositions();
77 	bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData);
78 	void updateStatusBarText();
79 	void drawBranchLine(HDC hdc, std::map<u32,int>& addressPositions, BranchLine& line);
80 	void copyInstructions(u32 startAddr, u32 endAddr, bool withDisasm);
81 	std::set<std::string> getSelectedLineArguments();
82 	void drawArguments(HDC hdc, const DisassemblyLineInfo &line, int x, int y, int textColor, const std::set<std::string> &currentArguments);
83 
84 public:
85 	CtrlDisAsmView(HWND _wnd);
86 	~CtrlDisAsmView();
87 	static void init();
88 	static void deinit();
89 	static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
90 	static CtrlDisAsmView * getFrom(HWND wnd);
91 
92 	void onChar(WPARAM wParam, LPARAM lParam);
93 	void onPaint(WPARAM wParam, LPARAM lParam);
94 	void onVScroll(WPARAM wParam, LPARAM lParam);
95 	void onKeyDown(WPARAM wParam, LPARAM lParam);
96 	void onKeyUp(WPARAM wParam, LPARAM lParam);
97 	void onMouseDown(WPARAM wParam, LPARAM lParam, int button);
98 	void onMouseUp(WPARAM wParam, LPARAM lParam, int button);
99 	void onMouseMove(WPARAM wParam, LPARAM lParam, int button);
100 	void scrollAddressIntoView();
101 	bool curAddressIsVisible();
102 	void redraw();
103 	void scanFunctions();
clearFunctions()104 	void clearFunctions() { manager.clear(); };
105 
106 	void getOpcodeText(u32 address, char* dest, int bufsize);
getRowHeight()107 	int getRowHeight() { return rowHeight; };
108 	u32 yToAddress(int y);
109 
setDontRedraw(bool b)110 	void setDontRedraw(bool b) { dontRedraw = b; };
setDebugger(DebugInterface * deb)111 	void setDebugger(DebugInterface *deb)
112 	{
113 		debugger=deb;
114 		curAddress=debugger->getPC();
115 		manager.setCpu(deb);
116 	}
getDebugger()117 	DebugInterface *getDebugger()
118 	{
119 		return debugger;
120 	}
121 
122 	void scrollStepping(u32 newPc);
123 	u32 getInstructionSizeAt(u32 address);
124 
gotoAddr(unsigned int addr)125 	void gotoAddr(unsigned int addr)
126 	{
127 		u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
128 		u32 newAddress = manager.getStartAddress(addr);
129 
130 		if (newAddress < windowStart || newAddress >= windowEnd)
131 		{
132 			windowStart = manager.getNthPreviousAddress(newAddress,visibleRows/2);
133 		}
134 
135 		setCurAddress(newAddress);
136 		scanFunctions();
137 		redraw();
138 	}
gotoPC()139 	void gotoPC()
140 	{
141 		gotoAddr(debugger->getPC());
142 	}
getSelection()143 	u32 getSelection()
144 	{
145 		return curAddress;
146 	}
147 
setShowMode(bool s)148 	void setShowMode(bool s)
149 	{
150 		showHex=s;
151 	}
152 
153 	void toggleBreakpoint(bool toggleEnabled = false);
154 	void editBreakpoint();
155 
scrollWindow(int lines)156 	void scrollWindow(int lines)
157 	{
158 		if (lines < 0)
159 			windowStart = manager.getNthPreviousAddress(windowStart,abs(lines));
160 		else
161 			windowStart = manager.getNthNextAddress(windowStart,lines);
162 
163 		scanFunctions();
164 		redraw();
165 	}
166 
167 	void setCurAddress(u32 newAddress, bool extend = false)
168 	{
169 		newAddress = manager.getStartAddress(newAddress);
170 		u32 after = manager.getNthNextAddress(newAddress,1);
171 		curAddress = newAddress;
172 		selectRangeStart = extend ? std::min(selectRangeStart, newAddress) : newAddress;
173 		selectRangeEnd = extend ? std::max(selectRangeEnd, after) : after;
174 		updateStatusBarText();
175 	}
176 };