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/
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"
28 #include "PowerPC/PowerPC.h"
32 #include "Debugger/PPCDebugInterface.h"
33 #include "PowerPC/PPCSymbolDB.h"
36 #include "LogManager.h"
38 #include "HW/Memmap.h"
41 // ugly that this lib included code from the main
42 #include "../../DolphinWX/Src/Globals.h"
46 IDM_MEM_ADDRBOX
= 350,
51 IDM_U8
,//Feel free to rename these
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
)
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
);
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
);
110 chkHex
->SetValue(1);//Set defaults
113 //sizerLeft->SetSizeHints(this);
114 //sizerLeft->Fit(this);
115 sizerRight
->SetSizeHints(this);
116 sizerRight
->Fit(this);
117 sizerBig
->SetSizeHints(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
)
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());
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());
164 if (!TryParseUInt(std::string("0x") + str_addr
, &addr
)) {
165 PanicAlert("Invalid Address: %s", str_addr
.c_str());
169 if (!TryParseUInt(std::string("0x") + str_val
, &val
)) {
170 PanicAlert("Invalid Value: %s", str_val
.c_str());
174 Memory::Write_U32(val
, addr
);
178 void CMemoryWindow::OnAddrBoxChange(wxCommandEvent
& event
)
180 wxString txt
= addrbox
->GetValue();
184 sscanf(txt
.mb_str(), "%08x", &addr
);
185 memview
->Center(addr
& ~3);
191 void CMemoryWindow::Update()
197 void CMemoryWindow::NotifyMapLoaded()
199 symbols
->Show(false); // hide it for faster filling
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);
217 void CMemoryWindow::OnSymbolListChange(wxCommandEvent
& event
)
219 int index
= symbols
->GetSelection();
221 Symbol
* pSymbol
= static_cast<Symbol
*>(symbols
->GetClientData(index
));
224 memview
->Center(pSymbol
->address
);
229 void CMemoryWindow::OnHostMessage(wxCommandEvent
& event
)
231 switch (event
.GetId())
233 case IDM_NOTIFYMAPLOADED
:
239 // so we can view memory in a tile/hex viewer for data analysis
240 void CMemoryWindow::OnDumpMemory( wxCommandEvent
& event
)
242 switch (memview
->GetMemoryType())
247 FILE* pDumpFile
= fopen(File::GetUserPath(F_RAMDUMP_IDX
), "wb");
252 fwrite(Memory::m_pRAM
, Memory::REALRAM_SIZE
, 1, pDumpFile
);
261 FILE* pDumpFile
= fopen(File::GetUserPath(F_ARAMDUMP_IDX
), "wb");
264 u8
* aram
= DSP::GetARAMPtr();
267 fwrite(aram
, DSP::ARAM_SIZE
, 1, pDumpFile
);
277 void CMemoryWindow::U8(wxCommandEvent
& event
) {
280 memview
->dataType
= 0;
283 void CMemoryWindow::U16(wxCommandEvent
& event
) {
286 memview
->dataType
= 1;
289 void CMemoryWindow::U32(wxCommandEvent
& event
) {
292 memview
->dataType
= 2;
296 void CMemoryWindow::onSearch(wxCommandEvent
& event
) {
299 switch (memview
->GetMemoryType())
305 TheRAM
=Memory::m_pRAM
;
306 szRAM
=Memory::REALRAM_SIZE
;
311 u8
* aram
= DSP::GetARAMPtr();
315 szRAM
=DSP::ARAM_SIZE
;
320 //Now we have memory to look in
321 //Are we looking for ASCII string, or hex?
323 wxString rawData
=valbox
->GetValue();
324 std::vector
<u8
> Dest
;//May need a better name
326 int pad
=rawData
.size()%2;//If it's uneven
331 unsigned char *tmp2
=0;
333 switch (chkHex
->GetValue()){
334 case 1://We are looking for hex
336 size
=(rawData
.size()/2) + pad
;
337 Dest
.resize(size
+32);
338 newsize
=rawData
.size();
341 tmpstr
= new char[newsize
+ 2];
342 memset(tmpstr
, 0, newsize
+ 2);
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());
354 for(i
=0;i
<strlen(tmpstr
);i
++){
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
366 case 0://Looking for an ascii string
369 tmpstr
=new char[size
+1];
373 sprintf(tmpstr
,"%s",(const char *)rawData
.mb_str());
381 unsigned char* pnt
=&Dest
.front();
384 wxString txt
= addrbox
->GetValue();
388 sscanf(txt
.mb_str(), "%08x", &addr
);
395 if(pnt
[k
]!=TheRAM
[i
+k
]){
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
);
413 wxMessageBox(_T("No match was found."));
417 void CMemoryWindow::onAscii(wxCommandEvent
& event
) {
421 void CMemoryWindow::onHex(wxCommandEvent
& event
) {
422 chkAscii
->SetValue(0);