| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | // Copyright (C) 2003-2008 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Debugger.h"
 | 
					
						
							|  |  |  | #include "Debugger/PPCDebugInterface.h"
 | 
					
						
							|  |  |  | #include "PowerPC/SymbolDB.h"
 | 
					
						
							|  |  |  | #include "HW/Memmap.h" // for Write_U32
 | 
					
						
							|  |  |  | #include "Common.h"
 | 
					
						
							|  |  |  | #include "StringUtil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Host.h"
 | 
					
						
							|  |  |  | #include "CodeView.h"
 | 
					
						
							|  |  |  | #include "JitWindow.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <wx/event.h>
 | 
					
						
							|  |  |  | #include <wx/clipbrd.h>
 | 
					
						
							|  |  |  | #include <wx/textdlg.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_EVENT_TYPE(wxEVT_CODEVIEW_CHANGE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDM_GOTOINMEMVIEW = 12000, | 
					
						
							|  |  |  | 	IDM_COPYADDRESS, | 
					
						
							|  |  |  | 	IDM_COPYHEX, | 
					
						
							|  |  |  | 	IDM_COPYCODE, | 
					
						
							|  |  |  | 	IDM_INSERTBLR, | 
					
						
							|  |  |  | 	IDM_RUNTOHERE, | 
					
						
							|  |  |  | 	IDM_JITRESULTS, | 
					
						
							|  |  |  | 	IDM_FOLLOWBRANCH, | 
					
						
							|  |  |  | 	IDM_RENAMESYMBOL, | 
					
						
							|  |  |  | 	IDM_PATCHALERT, | 
					
						
							|  |  |  | 	IDM_COPYFUNCTION, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BEGIN_EVENT_TABLE(CCodeView, wxControl) | 
					
						
							|  |  |  | 	EVT_ERASE_BACKGROUND(CCodeView::OnErase) | 
					
						
							|  |  |  | 	EVT_PAINT(CCodeView::OnPaint) | 
					
						
							|  |  |  | 	EVT_LEFT_DOWN(CCodeView::OnMouseDown) | 
					
						
							|  |  |  | 	EVT_LEFT_UP(CCodeView::OnMouseUpL) | 
					
						
							|  |  |  | 	EVT_MOTION(CCodeView::OnMouseMove) | 
					
						
							|  |  |  | 	EVT_RIGHT_DOWN(CCodeView::OnMouseDown) | 
					
						
							|  |  |  | 	EVT_RIGHT_UP(CCodeView::OnMouseUpR) | 
					
						
							|  |  |  | 	EVT_MENU(-1, CCodeView::OnPopupMenu) | 
					
						
							|  |  |  | END_EVENT_TABLE() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CCodeView::CCodeView(DebugInterface* debuginterface, wxWindow* parent, wxWindowID Id, const wxSize& Size) | 
					
						
							|  |  |  | 	: wxControl(parent, Id, wxDefaultPosition, Size), | 
					
						
							|  |  |  |       debugger(debuginterface), | 
					
						
							|  |  |  |       rowHeight(13), | 
					
						
							|  |  |  |       selection(0), | 
					
						
							|  |  |  |       oldSelection(0), | 
					
						
							|  |  |  |       selectionChanged(false), | 
					
						
							|  |  |  |       selecting(false), | 
					
						
							|  |  |  |       hasFocus(false), | 
					
						
							|  |  |  |       showHex(false), | 
					
						
							|  |  |  |       lx(-1), | 
					
						
							|  |  |  |       ly(-1) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	rowHeight = 13; | 
					
						
							|  |  |  | 	align = debuginterface->getInstructionSize(0); | 
					
						
							|  |  |  | 	curAddress = debuginterface->getPC(); | 
					
						
							|  |  |  | 	selection = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wxSize CCodeView::DoGetBestSize() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wxSize bestSize; | 
					
						
							|  |  |  | 	bestSize.x = 400; | 
					
						
							|  |  |  | 	bestSize.y = 800; | 
					
						
							|  |  |  | 	return(bestSize); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CCodeView::YToAddress(int y) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wxRect rc = GetClientRect(); | 
					
						
							|  |  |  | 	int ydiff = y - rc.height / 2 - rowHeight / 2; | 
					
						
							|  |  |  | 	ydiff = (int)(floorf((float)ydiff / (float)rowHeight)) + 1; | 
					
						
							|  |  |  | 	return(curAddress + ydiff * align); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnMouseDown(wxMouseEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int x = event.m_x; | 
					
						
							|  |  |  | 	int y = event.m_y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (x > 16) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		oldSelection = selection; | 
					
						
							|  |  |  | 		selection = YToAddress(y); | 
					
						
							|  |  |  | 		// SetCapture(wnd);
 | 
					
						
							|  |  |  | 		bool oldselecting = selecting; | 
					
						
							|  |  |  | 		selecting = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!oldselecting || (selection != oldSelection)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			redraw(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		debugger->toggleBreakpoint(YToAddress(y)); | 
					
						
							|  |  |  | 		redraw(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	event.Skip(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnMouseMove(wxMouseEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wxRect rc = GetClientRect(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (event.m_leftDown) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (event.m_x > 16) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (event.m_y < 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				curAddress -= align; | 
					
						
							|  |  |  | 				redraw(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (event.m_y > rc.height) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				curAddress += align; | 
					
						
							|  |  |  | 				redraw(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				OnMouseDown(event); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	event.Skip(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::RaiseEvent() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wxCommandEvent ev(wxEVT_CODEVIEW_CHANGE, GetId()); | 
					
						
							|  |  |  | 	ev.SetEventObject(this); | 
					
						
							|  |  |  | 	ev.SetInt(selection); | 
					
						
							|  |  |  | 	GetEventHandler()->ProcessEvent(ev); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnMouseUpL(wxMouseEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (event.m_x > 16) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		curAddress = YToAddress(event.m_y); | 
					
						
							|  |  |  | 		selecting = false; | 
					
						
							|  |  |  | 		//ReleaseCapture();
 | 
					
						
							|  |  |  | 		redraw(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	RaiseEvent(); | 
					
						
							|  |  |  | 	event.Skip(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 CCodeView::AddrToBranch(u32 addr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-09 21:24:12 +00:00
										 |  |  | 	char disasm[256]; | 
					
						
							|  |  |  | 	debugger->disasm(addr, disasm, 256); | 
					
						
							|  |  |  | 	const char *mojs = strstr(disasm, "->0x"); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	if (mojs) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		u32 dest; | 
					
						
							|  |  |  | 		sscanf(mojs+4,"%08x", &dest); | 
					
						
							|  |  |  | 		return dest; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnPopupMenu(wxCommandEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if wxUSE_CLIPBOARD
 | 
					
						
							|  |  |  | 	wxTheClipboard->Open(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (event.GetId()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    case IDM_GOTOINMEMVIEW: | 
					
						
							|  |  |  | 		    // CMemoryDlg::Goto(selection);
 | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if wxUSE_CLIPBOARD
 | 
					
						
							|  |  |  | 	    case IDM_COPYADDRESS: | 
					
						
							|  |  |  | 		    wxTheClipboard->SetData(new wxTextDataObject(wxString::Format(_T("%08x"), selection))); | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 21:24:12 +00:00
										 |  |  | 		case IDM_COPYCODE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			char disasm[256]; | 
					
						
							|  |  |  | 			debugger->disasm(selection, disasm, 256); | 
					
						
							|  |  |  | 		    wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(disasm))); //Have to manually convert from char* to wxString, don't have to in Windows?
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		    break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    case IDM_COPYHEX: | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		    char temp[24]; | 
					
						
							|  |  |  | 		    sprintf(temp, "%08x", debugger->readInstruction(selection)); | 
					
						
							|  |  |  | 		    wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp))); | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 		case IDM_COPYFUNCTION: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			Symbol *symbol = g_symbolDB.GetSymbolFromAddr(selection); | 
					
						
							|  |  |  | 			if (symbol) { | 
					
						
							|  |  |  | 				std::string text; | 
					
						
							|  |  |  | 				text = text + symbol->name + "\r\n"; | 
					
						
							|  |  |  | 				// we got a function
 | 
					
						
							|  |  |  | 				u32 start = symbol->address; | 
					
						
							|  |  |  | 				u32 end = start + symbol->size; | 
					
						
							|  |  |  | 				for (u32 addr = start; addr != end; addr += 4) { | 
					
						
							| 
									
										
										
										
											2008-12-09 21:24:12 +00:00
										 |  |  | 					char disasm[256]; | 
					
						
							|  |  |  | 					debugger->disasm(addr, disasm, 256); | 
					
						
							|  |  |  | 					text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n"; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(text.c_str()))); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    case IDM_RUNTOHERE: | 
					
						
							|  |  |  | 		    debugger->setBreakpoint(selection); | 
					
						
							|  |  |  | 		    debugger->runToBreakpoint(); | 
					
						
							|  |  |  | 		    redraw(); | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Insert blr or restore old value
 | 
					
						
							|  |  |  | 		case IDM_INSERTBLR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// Check if this address has been modified
 | 
					
						
							|  |  |  | 				int find = -1;				 | 
					
						
							|  |  |  | 				for(u32 i = 0; i < BlrList.size(); i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if(BlrList.at(i).Address == selection) | 
					
						
							|  |  |  | 					{ find = i; break;  }					 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Save the old value				
 | 
					
						
							|  |  |  | 				if(find >= 0) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Memory::Write_U32(BlrList.at(find).OldValue, selection); | 
					
						
							|  |  |  | 					BlrList.erase(BlrList.begin() + find); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					BlrStruct Temp; | 
					
						
							|  |  |  | 					Temp.Address = selection; | 
					
						
							|  |  |  | 					Temp.OldValue = debugger->readMemory(selection); | 
					
						
							|  |  |  | 					BlrList.push_back(Temp); | 
					
						
							|  |  |  | 					debugger->insertBLR(selection);					 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				redraw(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    case IDM_JITRESULTS: | 
					
						
							|  |  |  | 			CJitWindow::ViewAddr(selection); | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case IDM_FOLLOWBRANCH: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			u32 dest = AddrToBranch(selection); | 
					
						
							|  |  |  | 			if (dest) | 
					
						
							|  |  |  | 				Center(dest); | 
					
						
							|  |  |  | 				RaiseEvent(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		case IDM_RENAMESYMBOL: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			Symbol *symbol = g_symbolDB.GetSymbolFromAddr(selection); | 
					
						
							|  |  |  | 			if (symbol) { | 
					
						
							|  |  |  | 				wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"), wxGetTextFromUserPromptStr, | 
					
						
							|  |  |  | 					wxString::FromAscii(symbol->name.c_str())); | 
					
						
							|  |  |  | 				if (input_symbol.ShowModal() == wxID_OK) { | 
					
						
							|  |  |  | 					symbol->name = input_symbol.GetValue().mb_str(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | //			    redraw();
 | 
					
						
							|  |  |  | 				Host_NotifyMapLoaded(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case IDM_PATCHALERT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if wxUSE_CLIPBOARD
 | 
					
						
							|  |  |  | 	wxTheClipboard->Close(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	event.Skip(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnMouseUpR(wxMouseEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bool isSymbol = g_symbolDB.GetSymbolFromAddr(selection) != 0; | 
					
						
							|  |  |  | 	// popup menu
 | 
					
						
							|  |  |  | 	wxMenu menu; | 
					
						
							|  |  |  | 	//menu.Append(IDM_GOTOINMEMVIEW, "&Goto in mem view");
 | 
					
						
							|  |  |  | 	menu.Append(IDM_FOLLOWBRANCH, wxString::FromAscii("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false); | 
					
						
							|  |  |  | 	menu.AppendSeparator(); | 
					
						
							|  |  |  | #if wxUSE_CLIPBOARD
 | 
					
						
							|  |  |  | 	menu.Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address")); | 
					
						
							|  |  |  | 	menu.Append(IDM_COPYFUNCTION, wxString::FromAscii("Copy &function"))->Enable(isSymbol); | 
					
						
							|  |  |  | 	menu.Append(IDM_COPYCODE, wxString::FromAscii("Copy &code line")); | 
					
						
							|  |  |  | 	menu.Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex")); | 
					
						
							|  |  |  | 	menu.AppendSeparator(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	menu.Append(IDM_RENAMESYMBOL, wxString::FromAscii("Rename &symbol"))->Enable(isSymbol); | 
					
						
							|  |  |  | 	menu.AppendSeparator(); | 
					
						
							|  |  |  | 	menu.Append(IDM_RUNTOHERE, _T("&Run To Here")); | 
					
						
							|  |  |  | 	menu.Append(IDM_JITRESULTS, wxString::FromAscii("PPC vs X86")); | 
					
						
							|  |  |  | 	menu.Append(IDM_INSERTBLR, wxString::FromAscii("Insert &blr")); | 
					
						
							|  |  |  | 	menu.Append(IDM_PATCHALERT, wxString::FromAscii("Patch alert")); | 
					
						
							|  |  |  | 	PopupMenu(&menu); | 
					
						
							|  |  |  | 	event.Skip(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnErase(wxEraseEvent& event) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::OnPaint(wxPaintEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 	// General settings
 | 
					
						
							|  |  |  | 	// -------------------------
 | 
					
						
							|  |  |  | 	wxPaintDC dc(this); | 
					
						
							|  |  |  | 	wxRect rc = GetClientRect(); | 
					
						
							|  |  |  | 	wxFont font(7, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT); | 
					
						
							|  |  |  | 	dc.SetFont(font); | 
					
						
							|  |  |  | 	struct branch | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int src, dst, srcAddr; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	branch branches[256]; | 
					
						
							|  |  |  | 	int numBranches = 0; | 
					
						
							|  |  |  | 	// TODO: Add any drawing code here...
 | 
					
						
							|  |  |  | 	int width   = rc.width; | 
					
						
							|  |  |  | 	int numRows = (rc.height / rowHeight) / 2 + 2; | 
					
						
							|  |  |  | 	//numRows=(numRows&(~1)) + 1;
 | 
					
						
							|  |  |  | 	// ------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 	// Colors and brushes
 | 
					
						
							|  |  |  | 	// -------------------------	
 | 
					
						
							|  |  |  | 	dc.SetBackgroundMode(wxTRANSPARENT); // the text background
 | 
					
						
							|  |  |  | 	const wxChar* bgColor = _T("#ffffff"); | 
					
						
							|  |  |  | 	wxPen nullPen(bgColor); | 
					
						
							|  |  |  | 	wxPen currentPen(_T("#000000")); | 
					
						
							|  |  |  | 	wxPen selPen(_T("#808080")); // gray
 | 
					
						
							|  |  |  | 	nullPen.SetStyle(wxTRANSPARENT); | 
					
						
							|  |  |  | 	currentPen.SetStyle(wxSOLID); | 
					
						
							|  |  |  | 	wxBrush currentBrush(_T("#FFEfE8")); // the ... ? ... is light gray
 | 
					
						
							|  |  |  | 	wxBrush pcBrush(_T("#70FF70")); // the selected code line is green	
 | 
					
						
							|  |  |  | 	wxBrush bpBrush(_T("#FF3311")); // red
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wxBrush bgBrush(bgColor); | 
					
						
							|  |  |  | 	wxBrush nullBrush(bgColor); | 
					
						
							|  |  |  | 	nullBrush.SetStyle(wxTRANSPARENT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dc.SetPen(nullPen); | 
					
						
							|  |  |  | 	dc.SetBrush(bgBrush); | 
					
						
							|  |  |  | 	dc.DrawRectangle(0, 0, 16, rc.height); | 
					
						
							|  |  |  | 	dc.DrawRectangle(0, 0, rc.width, 5); | 
					
						
							|  |  |  | 	// ------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 	// Walk through all visible rows
 | 
					
						
							|  |  |  | 	// -------------------------
 | 
					
						
							|  |  |  | 	for (int i = -numRows; i <= numRows; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		unsigned int address = curAddress + i * align; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int rowY1 = rc.height / 2 + rowHeight * i - rowHeight / 2; | 
					
						
							|  |  |  | 		int rowY2 = rc.height / 2 + rowHeight * i + rowHeight / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		wxString temp = wxString::Format(_T("%08x"), address); | 
					
						
							|  |  |  | 		u32 col = debugger->getColor(address); | 
					
						
							|  |  |  | 		wxBrush rowBrush(wxColor(col >> 16, col >> 8, col)); | 
					
						
							|  |  |  | 		dc.SetBrush(nullBrush); | 
					
						
							|  |  |  | 		dc.SetPen(nullPen); | 
					
						
							|  |  |  | 		dc.DrawRectangle(0, rowY1, 16, rowY2 - rowY1 + 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (selecting && (address == selection)) | 
					
						
							|  |  |  | 			dc.SetPen(selPen); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			dc.SetPen(i == 0 ? currentPen : nullPen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (address == debugger->getPC()) | 
					
						
							|  |  |  | 			dc.SetBrush(pcBrush); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			dc.SetBrush(rowBrush); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dc.DrawRectangle(16, rowY1, width, rowY2 - rowY1 + 1); | 
					
						
							|  |  |  | 		dc.SetBrush(currentBrush); | 
					
						
							|  |  |  | 		dc.SetTextForeground(_T("#600000")); // the address text is dark red
 | 
					
						
							|  |  |  | 		dc.DrawText(temp, 17, rowY1); | 
					
						
							|  |  |  | 		dc.SetTextForeground(_T("#000000")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (debugger->isAlive()) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-12-09 21:24:12 +00:00
										 |  |  | 			char dis[256]; | 
					
						
							|  |  |  | 			debugger->disasm(address, dis, 256); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			char* dis2 = strchr(dis, '\t'); | 
					
						
							|  |  |  | 			char desc[256] = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// If we have a code
 | 
					
						
							|  |  |  | 			if (dis2) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*dis2 = 0; | 
					
						
							|  |  |  | 				dis2++; | 
					
						
							|  |  |  | 				const char* mojs = strstr(dis2, "0x8"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 				// Colors and brushes
 | 
					
						
							|  |  |  | 				// -------------------------
 | 
					
						
							|  |  |  | 				if (mojs) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					for (int k = 0; k < 8; k++) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						bool found = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						for (int j = 0; j < 22; j++) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							if (mojs[k + 2] == "0123456789ABCDEFabcdef"[j]) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								found = true; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (!found) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							mojs = 0; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// ------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 				// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 				// Colors and brushes
 | 
					
						
							|  |  |  | 				// -------------------------
 | 
					
						
							|  |  |  | 				if (mojs) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					int offs; | 
					
						
							|  |  |  | 					sscanf(mojs + 2, "%08x", &offs); | 
					
						
							|  |  |  | 					branches[numBranches].src = rowY1 + rowHeight / 2; | 
					
						
							|  |  |  | 					branches[numBranches].srcAddr = address / align; | 
					
						
							|  |  |  | 					branches[numBranches++].dst = (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * rowHeight / align + rowHeight / 2); | 
					
						
							|  |  |  | 					sprintf(desc, "-->%s", debugger->getDescription(offs).c_str()); | 
					
						
							|  |  |  | 					dc.SetTextForeground(_T("#600060")); // the -> arrow illustrations are purple
 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					dc.SetTextForeground(_T("#000000")); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				dc.DrawText(wxString::FromAscii(dis2), 126, rowY1); | 
					
						
							|  |  |  | 				// ------------
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Show blr as its' own color
 | 
					
						
							|  |  |  | 			if (strcmp(dis, "blr")) | 
					
						
							|  |  |  | 				dc.SetTextForeground(_T("#007000")); // dark green
 | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				dc.SetTextForeground(_T("#8000FF")); // purple
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dc.DrawText(wxString::FromAscii(dis), 70, rowY1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (desc[0] == 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				strcpy(desc, debugger->getDescription(address).c_str()); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dc.SetTextForeground(_T("#0000FF")); // blue
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//char temp[256];
 | 
					
						
							|  |  |  | 			//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
 | 
					
						
							|  |  |  | 			if (strlen(desc)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				dc.DrawText(wxString::FromAscii(desc), 235, rowY1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Show red breakpoint dot
 | 
					
						
							|  |  |  | 			if (debugger->isBreakpoint(address)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				dc.SetBrush(bpBrush); | 
					
						
							|  |  |  | 				dc.DrawRectangle(2, rowY1, 7, 7); | 
					
						
							|  |  |  | 				//DrawIconEx(hdc, 2, rowY1, breakPoint, 32, 32, 0, 0, DI_NORMAL);
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} // end of for
 | 
					
						
							|  |  |  | 	// ------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 	// Colors and brushes
 | 
					
						
							|  |  |  | 	// -------------------------
 | 
					
						
							|  |  |  | 	dc.SetPen(currentPen); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (int i = 0; i < numBranches; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    int x = 300 + (branches[i].srcAddr % 9) * 8; | 
					
						
							|  |  |  | 	    _MoveTo(x-2, branches[i].src); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (branches[i].dst < rc.height + 400 && branches[i].dst > -400) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 			_LineTo(dc, x+2, branches[i].src); | 
					
						
							|  |  |  | 			_LineTo(dc, x+2, branches[i].dst); | 
					
						
							|  |  |  | 			_LineTo(dc, x-4, branches[i].dst); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_MoveTo(x, branches[i].dst - 4); | 
					
						
							|  |  |  | 			_LineTo(dc, x-4, branches[i].dst); | 
					
						
							|  |  |  | 			_LineTo(dc, x+1, branches[i].dst+5); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 			_LineTo(dc, x+4, branches[i].src); | 
					
						
							|  |  |  | 			//MoveToEx(hdc,x+2,branches[i].dst-4,0);
 | 
					
						
							|  |  |  | 			//LineTo(hdc,x+6,branches[i].dst);
 | 
					
						
							|  |  |  | 			//LineTo(hdc,x+1,branches[i].dst+5);
 | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    //LineTo(hdc,x,branches[i].dst+4);
 | 
					
						
							|  |  |  | 	    //LineTo(hdc,x-2,branches[i].dst);
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// ------------
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CCodeView::_LineTo(wxPaintDC &dc, int x, int y) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	dc.DrawLine(lx, ly, x, y); | 
					
						
							|  |  |  | 	lx = x; | 
					
						
							|  |  |  | 	ly = y; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |