Lots more work on making the frame aui stuff functional.
[dolphin.git] / Source / Core / DebuggerWX / Src / MemoryWindow.cpp
blobc6375ade4e88ca1da5a9c6eaa52ada100b1aee54
1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include "Debugger.h"
21 #include <wx/button.h>
22 #include <wx/textctrl.h>
23 #include <wx/listctrl.h>
24 #include <wx/thread.h>
25 #include <wx/listctrl.h>
26 #include "MemoryWindow.h"
27 #include "HW/CPU.h"
28 #include "PowerPC/PowerPC.h"
29 #include "Host.h"
30 #include "FileUtil.h"
32 #include "Debugger/PPCDebugInterface.h"
33 #include "PowerPC/PPCSymbolDB.h"
35 #include "Core.h"
36 #include "LogManager.h"
38 #include "HW/Memmap.h"
39 #include "HW/DSP.h"
41 // ugly that this lib included code from the main
42 #include "../../DolphinWX/Src/Globals.h"
44 enum
46 IDM_MEM_ADDRBOX = 350,
47 IDM_SYMBOLLIST,
48 IDM_SETVALBUTTON,
49 IDM_DUMP_MEMORY,
50 IDM_VALBOX,
51 IDM_U8,//Feel free to rename these
52 IDM_U16,
53 IDM_U32,
54 IDM_SEARCH,
55 IDM_ASCII,
56 IDM_HEX
59 BEGIN_EVENT_TABLE(CMemoryWindow, wxPanel)
60 EVT_TEXT(IDM_MEM_ADDRBOX, CMemoryWindow::OnAddrBoxChange)
61 EVT_LISTBOX(IDM_SYMBOLLIST, CMemoryWindow::OnSymbolListChange)
62 EVT_HOST_COMMAND(wxID_ANY, CMemoryWindow::OnHostMessage)
63 EVT_BUTTON(IDM_SETVALBUTTON, CMemoryWindow::SetMemoryValue)
64 EVT_BUTTON(IDM_DUMP_MEMORY, CMemoryWindow::OnDumpMemory)
65 EVT_CHECKBOX(IDM_U8 , CMemoryWindow::U8)
66 EVT_CHECKBOX(IDM_U16 , CMemoryWindow::U16)
67 EVT_CHECKBOX(IDM_U32 , CMemoryWindow::U32)
68 EVT_BUTTON(IDM_SEARCH , CMemoryWindow::onSearch)
69 EVT_CHECKBOX(IDM_ASCII , CMemoryWindow::onAscii)
70 EVT_CHECKBOX(IDM_HEX , CMemoryWindow::onHex)
71 END_EVENT_TABLE()
73 CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id,
74 const wxPoint& pos, const wxSize& size, long style, const wxString& name)
75 : wxPanel(parent, id, pos, size, style, name)
77 wxBoxSizer* sizerBig = new wxBoxSizer(wxHORIZONTAL);
78 wxBoxSizer* sizerRight = new wxBoxSizer(wxVERTICAL);
79 // didn't see anything usefull in the left part
80 //wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
82 DebugInterface* di = &PowerPC::debug_interface;
84 //sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(20, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
85 memview = new CMemoryView(di, this, wxID_ANY);
86 memview->dataType=0;
87 //sizerBig->Add(sizerLeft, 1, wxEXPAND);
88 sizerBig->Add(memview, 20, wxEXPAND);
89 sizerBig->Add(sizerRight, 0, wxEXPAND | wxALL, 3);
90 sizerRight->Add(addrbox = new wxTextCtrl(this, IDM_MEM_ADDRBOX, _T("")));
91 sizerRight->Add(valbox = new wxTextCtrl(this, IDM_VALBOX, _T("")));
92 sizerRight->Add(new wxButton(this, IDM_SETVALBUTTON, _T("Set &Value")));
94 sizerRight->AddSpacer(5);
95 sizerRight->Add(new wxButton(this, IDM_DUMP_MEMORY, _T("&Dump Memory")));
97 wxStaticBoxSizer* sizerSearchType = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Search"));
99 sizerSearchType->Add(btnSearch=new wxButton(this,IDM_SEARCH,_T("Search")));
100 sizerSearchType->Add(chkAscii=new wxCheckBox(this,IDM_ASCII,_T("&Ascii ")));
101 sizerSearchType->Add(chkHex=new wxCheckBox(this,IDM_HEX,_T("&Hex")));
102 sizerRight->Add(sizerSearchType);
103 wxStaticBoxSizer* sizerDataTypes = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Data Type"));
105 sizerDataTypes->Add(chk8=new wxCheckBox(this,IDM_U8,_T("&U8 ")));//Excesss spaces are to get the DataType to show properly
106 sizerDataTypes->Add(chk16=new wxCheckBox(this,IDM_U16,_T("&U16 ")));
107 sizerDataTypes->Add(chk32=new wxCheckBox(this,IDM_U32,_T("&U32 ")));
108 sizerRight->Add(sizerDataTypes);
109 SetSizer(sizerBig);
110 chkHex->SetValue(1);//Set defaults
111 chk8->SetValue(1);
113 //sizerLeft->SetSizeHints(this);
114 //sizerLeft->Fit(this);
115 sizerRight->SetSizeHints(this);
116 sizerRight->Fit(this);
117 sizerBig->SetSizeHints(this);
118 sizerBig->Fit(this);
122 CMemoryWindow::~CMemoryWindow()
127 void CMemoryWindow::Save(IniFile& _IniFile) const
129 // Prevent these bad values that can happen after a crash or hanging
130 if(GetPosition().x != -32000 && GetPosition().y != -32000)
132 _IniFile.Set("MemoryWindow", "x", GetPosition().x);
133 _IniFile.Set("MemoryWindow", "y", GetPosition().y);
134 _IniFile.Set("MemoryWindow", "w", GetSize().GetWidth());
135 _IniFile.Set("MemoryWindow", "h", GetSize().GetHeight());
140 void CMemoryWindow::Load(IniFile& _IniFile)
142 int x,y,w,h;
143 _IniFile.Get("MemoryWindow", "x", &x, GetPosition().x);
144 _IniFile.Get("MemoryWindow", "y", &y, GetPosition().y);
145 _IniFile.Get("MemoryWindow", "w", &w, GetSize().GetWidth());
146 _IniFile.Get("MemoryWindow", "h", &h, GetSize().GetHeight());
147 SetSize(x, y, w, h);
151 void CMemoryWindow::JumpToAddress(u32 _Address)
153 memview->Center(_Address);
157 void CMemoryWindow::SetMemoryValue(wxCommandEvent& event)
159 std::string str_addr = std::string(addrbox->GetValue().mb_str());
160 std::string str_val = std::string(valbox->GetValue().mb_str());
161 u32 addr;
162 u32 val;
164 if (!TryParseUInt(std::string("0x") + str_addr, &addr)) {
165 PanicAlert("Invalid Address: %s", str_addr.c_str());
166 return;
169 if (!TryParseUInt(std::string("0x") + str_val, &val)) {
170 PanicAlert("Invalid Value: %s", str_val.c_str());
171 return;
174 Memory::Write_U32(val, addr);
175 memview->Refresh();
178 void CMemoryWindow::OnAddrBoxChange(wxCommandEvent& event)
180 wxString txt = addrbox->GetValue();
181 if (txt.size())
183 u32 addr;
184 sscanf(txt.mb_str(), "%08x", &addr);
185 memview->Center(addr & ~3);
188 event.Skip(1);
191 void CMemoryWindow::Update()
193 memview->Refresh();
194 memview->Center(PC);
197 void CMemoryWindow::NotifyMapLoaded()
199 symbols->Show(false); // hide it for faster filling
200 symbols->Clear();
202 #ifdef _WIN32
203 const FunctionDB::XFuncMap &syms = g_symbolDB.Symbols();
204 for (FuntionDB::XFuncMap::iterator iter = syms.begin(); iter != syms.end(); ++iter)
206 int idx = symbols->Append(iter->second.name.c_str());
207 symbols->SetClientData(idx, (void*)&iter->second);
211 #endif
213 symbols->Show(true);
214 Update();
217 void CMemoryWindow::OnSymbolListChange(wxCommandEvent& event)
219 int index = symbols->GetSelection();
220 if (index >= 0) {
221 Symbol* pSymbol = static_cast<Symbol *>(symbols->GetClientData(index));
222 if (pSymbol != NULL)
224 memview->Center(pSymbol->address);
229 void CMemoryWindow::OnHostMessage(wxCommandEvent& event)
231 switch (event.GetId())
233 case IDM_NOTIFYMAPLOADED:
234 NotifyMapLoaded();
235 break;
239 // so we can view memory in a tile/hex viewer for data analysis
240 void CMemoryWindow::OnDumpMemory( wxCommandEvent& event )
242 switch (memview->GetMemoryType())
244 case 0:
245 default:
247 FILE* pDumpFile = fopen(File::GetUserPath(F_RAMDUMP_IDX), "wb");
248 if (pDumpFile)
250 if (Memory::m_pRAM)
252 fwrite(Memory::m_pRAM, Memory::REALRAM_SIZE, 1, pDumpFile);
254 fclose(pDumpFile);
257 break;
259 case 1:
261 FILE* pDumpFile = fopen(File::GetUserPath(F_ARAMDUMP_IDX), "wb");
262 if (pDumpFile)
264 u8* aram = DSP::GetARAMPtr();
265 if (aram)
267 fwrite(aram, DSP::ARAM_SIZE, 1, pDumpFile);
269 fclose(pDumpFile);
272 break;
277 void CMemoryWindow::U8(wxCommandEvent& event) {
278 chk16->SetValue(0);
279 chk32->SetValue(0);
280 memview->dataType = 0;
281 memview->Refresh();
283 void CMemoryWindow::U16(wxCommandEvent& event) {
284 chk8->SetValue(0);
285 chk32->SetValue(0);
286 memview->dataType = 1;
287 memview->Refresh();
289 void CMemoryWindow::U32(wxCommandEvent& event) {
290 chk16->SetValue(0);
291 chk8->SetValue(0);
292 memview->dataType = 2;
293 memview->Refresh();
296 void CMemoryWindow::onSearch(wxCommandEvent& event) {
297 u8* TheRAM=0;
298 u32 szRAM=0;
299 switch (memview->GetMemoryType())
301 case 0:
302 default:
303 if (Memory::m_pRAM)
305 TheRAM=Memory::m_pRAM;
306 szRAM=Memory::REALRAM_SIZE;
308 break;
309 case 1:
311 u8* aram = DSP::GetARAMPtr();
312 if (aram)
314 TheRAM=aram;
315 szRAM=DSP::ARAM_SIZE;
318 break;
320 //Now we have memory to look in
321 //Are we looking for ASCII string, or hex?
322 //memview->cu
323 wxString rawData=valbox->GetValue();
324 std::vector<u8> Dest;//May need a better name
325 u32 size=0;
326 int pad=rawData.size()%2;//If it's uneven
327 unsigned long i=0;
328 long count=0;
329 char copy[3]={0};
330 long newsize=0;
331 unsigned char *tmp2=0;
332 char* tmpstr=0;
333 switch (chkHex->GetValue()){
334 case 1://We are looking for hex
335 //If it's uneven
336 size=(rawData.size()/2) + pad;
337 Dest.resize(size+32);
338 newsize=rawData.size();
340 if (pad) {
341 tmpstr = new char[newsize + 2];
342 memset(tmpstr, 0, newsize + 2);
343 tmpstr[0]='0';
344 } else {
345 tmpstr = new char[newsize + 1];
346 memset(tmpstr, 0, newsize + 1);
348 //sprintf(tmpstr,"%s%s",tmpstr,rawData.c_str());
349 //strcpy(&tmpstr[1],rawData.ToAscii());
350 //memcpy(&tmpstr[1],&rawData.c_str()[0],rawData.size());
351 sprintf(tmpstr,"%s%s",tmpstr,(const char *)rawData.mb_str());
352 tmp2=&Dest.front();
353 count=0;
354 for(i=0;i<strlen(tmpstr);i++){
355 copy[0]=tmpstr[i];
356 copy[1]=tmpstr[i+1];
357 copy[2]=0;
358 int tmpint;
359 sscanf(copy, "%02x", &tmpint);
360 tmp2[count++] = tmpint;
361 //sscanf(copy,"%02x",&tmp2[count++]);//Dest[count] should now be the hex of what the two chars were! Also should add a check to make sure it's A-F only
362 i+=1;//
364 delete[] tmpstr;
365 break;
366 case 0://Looking for an ascii string
367 size=rawData.size();
368 Dest.resize(size+1);
369 tmpstr=new char[size+1];
372 tmp2=&Dest.front();
373 sprintf(tmpstr,"%s",(const char *)rawData.mb_str());
374 for(i=0;i<size;i++){
375 tmp2[i]=tmpstr[i];
377 delete[] tmpstr;
378 break;
380 if(size){
381 unsigned char* pnt=&Dest.front();
382 unsigned int k=0;
383 //grab
384 wxString txt = addrbox->GetValue();
385 u32 addr=0;
386 if (txt.size())
388 sscanf(txt.mb_str(), "%08x", &addr);
390 i=addr+4;
391 for(;i<szRAM;i++){
392 for(k=0;k<size;k++){
393 if(i+k>szRAM) break;
394 if(k>size) break;
395 if(pnt[k]!=TheRAM[i+k]){
396 k=0;
397 break;
400 if(k==size){
401 //Match was found
402 wxMessageBox(_T("A match was found. Placing viewer at the offset."));
403 wxChar tmpwxstr[128]={0};
404 wxSprintf(tmpwxstr,_T("%08x"),i);
405 wxString tmpwx(tmpwxstr);
406 addrbox->SetValue(tmpwx);
407 //memview->curAddress=i;
408 //memview->Refresh();
409 OnAddrBoxChange(event);
410 return;
413 wxMessageBox(_T("No match was found."));
417 void CMemoryWindow::onAscii(wxCommandEvent& event) {
418 chkHex->SetValue(0);
421 void CMemoryWindow::onHex(wxCommandEvent& event) {
422 chkAscii->SetValue(0);