1 #include "core/dispatch.hpp"
2 #include "core/memorymanip.hpp"
4 #include "plat-wxwidgets/platform.hpp"
11 #include <wx/control.h>
12 #include <wx/combobox.h>
14 #define wxID_RESET (wxID_HIGHEST + 1)
15 #define wxID_UPDATE (wxID_HIGHEST + 2)
16 #define wxID_TYPESELECT (wxID_HIGHEST + 3)
17 #define wxID_HEX_SELECT (wxID_HIGHEST + 4)
18 #define wxID_BUTTONS_BASE (wxID_HIGHEST + 128)
24 #define CANDIDATE_LIMIT 200
26 class wxwindow_memorysearch
;
29 wxwindow_memorysearch
* mwatch
;
30 const char* datatypes
[] = {
41 const char* searchtypes
[] = {
52 typedef void (memorysearch::*primitive_search_t
)();
54 primitive_search_t primitive_searches
[DATATYPES
][PRIMITIVES
] = {
55 { &memorysearch::byte_slt
, &memorysearch::byte_sle
, &memorysearch::byte_seq
, &memorysearch::byte_sne
,
56 &memorysearch::byte_sge
, &memorysearch::byte_sgt
, &memorysearch::update
},
57 { &memorysearch::byte_ult
, &memorysearch::byte_ule
, &memorysearch::byte_ueq
, &memorysearch::byte_une
,
58 &memorysearch::byte_uge
, &memorysearch::byte_ugt
, &memorysearch::update
},
59 { &memorysearch::word_slt
, &memorysearch::word_sle
, &memorysearch::word_seq
, &memorysearch::word_sne
,
60 &memorysearch::word_sge
, &memorysearch::word_sgt
, &memorysearch::update
},
61 { &memorysearch::word_ult
, &memorysearch::word_ule
, &memorysearch::word_ueq
, &memorysearch::word_une
,
62 &memorysearch::word_uge
, &memorysearch::word_ugt
, &memorysearch::update
},
63 { &memorysearch::dword_slt
, &memorysearch::dword_sle
, &memorysearch::dword_seq
,
64 &memorysearch::dword_sne
, &memorysearch::dword_sge
, &memorysearch::dword_sgt
, &memorysearch::update
},
65 { &memorysearch::dword_ult
, &memorysearch::dword_ule
, &memorysearch::dword_ueq
,
66 &memorysearch::dword_une
, &memorysearch::dword_uge
, &memorysearch::dword_ugt
, &memorysearch::update
},
67 { &memorysearch::qword_slt
, &memorysearch::qword_sle
, &memorysearch::qword_seq
,
68 &memorysearch::qword_sne
, &memorysearch::qword_sge
, &memorysearch::qword_sgt
, &memorysearch::update
},
69 { &memorysearch::qword_ult
, &memorysearch::qword_ule
, &memorysearch::qword_ueq
,
70 &memorysearch::qword_une
, &memorysearch::qword_uge
, &memorysearch::qword_ugt
, &memorysearch::update
}
73 std::string
hexformat_address(uint32_t addr
)
76 x
<< std::setfill('0') << std::setw(8) << std::hex
<< addr
;
80 template<typename T
> std::string
format_number_signed(T val
, bool hex
);
81 template<typename T
> std::string
format_number_unsigned(T val
, bool hex
);
83 template<typename T
> std::string
format_number_signedh(T val
, unsigned hwidth
, bool hex
)
88 x
<< "+" << std::setfill('0') << std::setw(hwidth
) << std::hex
<<
89 static_cast<uint64_t>(val
);
92 uint64_t y
= static_cast<uint64_t>(y2
);
93 x
<< "-" << std::setfill('0') << std::setw(hwidth
) << std::hex
<< (~y
+ 1);
96 x
<< static_cast<int64_t>(val
);
100 template<typename T
> std::string
format_number_unsignedh(T val
, unsigned hwidth
, bool hex
)
102 std::ostringstream x
;
104 x
<< std::setfill('0') << std::setw(hwidth
) << std::hex
<< static_cast<uint64_t>(val
);
106 x
<< static_cast<uint64_t>(val
);
110 template<> std::string format_number_signed
<uint8_t>(uint8_t val
, bool hex
)
112 return format_number_signedh(static_cast<int8_t>(val
), 2, hex
);
115 template<> std::string format_number_signed
<uint16_t>(uint16_t val
, bool hex
)
117 return format_number_signedh(static_cast<int16_t>(val
), 4, hex
);
120 template<> std::string format_number_signed
<uint32_t>(uint32_t val
, bool hex
)
122 return format_number_signedh(static_cast<int32_t>(val
), 8, hex
);
125 template<> std::string format_number_signed
<uint64_t>(uint64_t val
, bool hex
)
127 return format_number_signedh(static_cast<int64_t>(val
), 16, hex
);
130 template<> std::string format_number_unsigned
<uint8_t>(uint8_t val
, bool hex
)
132 return format_number_unsignedh(val
, 2, hex
);
135 template<> std::string format_number_unsigned
<uint16_t>(uint16_t val
, bool hex
)
137 return format_number_unsignedh(val
, 4, hex
);
140 template<> std::string format_number_unsigned
<uint32_t>(uint32_t val
, bool hex
)
142 return format_number_unsignedh(val
, 8, hex
);
145 template<> std::string format_number_unsigned
<uint64_t>(uint64_t val
, bool hex
)
147 return format_number_unsignedh(val
, 16, hex
);
151 class wxwindow_memorysearch
: public wxFrame
154 wxwindow_memorysearch();
155 ~wxwindow_memorysearch();
156 bool ShouldPreventAppExit() const;
157 void on_close(wxCloseEvent
& e
);
158 void on_button_click(wxCommandEvent
& e
);
161 template<typename T
> void valuesearch();
162 template<typename T
> void valuesearch2(T value
);
164 memorysearch
* msearch
;
168 wxCheckBox
* hexmode2
;
173 wxwindow_memorysearch::wxwindow_memorysearch()
174 : wxFrame(NULL
, wxID_ANY
, wxT("lsnes: Memory Search"), wxDefaultPosition
, wxSize(-1, -1),
175 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
)
180 Connect(wxEVT_CLOSE_WINDOW
, wxCloseEventHandler(wxwindow_memorysearch::on_close
));
181 msearch
= new memorysearch();
183 wxFlexGridSizer
* toplevel
= new wxFlexGridSizer(4, 1, 0, 0);
186 wxFlexGridSizer
* buttons
= new wxFlexGridSizer(1, 5, 0, 0);
187 buttons
->Add(tmp
= new wxButton(this, wxID_RESET
, wxT("Reset")), 0, wxGROW
);
188 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
190 buttons
->Add(tmp
= new wxButton(this, wxID_UPDATE
, wxT("Update")), 0, wxGROW
);
191 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
193 buttons
->Add(new wxStaticText(this, wxID_ANY
, wxT("Data type:")), 0, wxGROW
);
194 wxString _datatypes
[DATATYPES
];
195 for(size_t i
= 0; i
< DATATYPES
; i
++)
196 _datatypes
[i
] = towxstring(datatypes
[i
]);
197 buttons
->Add(type
= new wxComboBox(this, wxID_TYPESELECT
, _datatypes
[typecode
], wxDefaultPosition
,
198 wxDefaultSize
, DATATYPES
, _datatypes
, wxCB_READONLY
), 0,
200 type
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
201 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
202 buttons
->Add(hexmode2
= new wxCheckBox(this, wxID_HEX_SELECT
, wxT("Hex display")), 0, wxGROW
);
203 hexmode2
->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED
,
204 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
205 toplevel
->Add(buttons
);
207 wxFlexGridSizer
* searches
= new wxFlexGridSizer(1, BROW_SIZE
, 0, 0);
208 for(unsigned j
= 0; j
< BROW_SIZE
; j
++) {
209 searches
->Add(tmp
= new wxButton(this, wxID_BUTTONS_BASE
+ j
, towxstring(searchtypes
[j
])), 1, wxGROW
);
210 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
211 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
213 toplevel
->Add(searches
);
215 toplevel
->Add(count
= new wxStaticText(this, wxID_ANY
, wxT("XXX candidates")), 0, wxGROW
);
216 toplevel
->Add(matches
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(500, 300),
217 wxTE_MULTILINE
| wxTE_READONLY
| wxTE_DONTWRAP
), 1, wxGROW
);
219 toplevel
->SetSizeHints(this);
225 wxwindow_memorysearch::~wxwindow_memorysearch()
231 bool wxwindow_memorysearch::ShouldPreventAppExit() const
236 void wxwindow_memorysearch::on_close(wxCloseEvent
& e
)
242 void wxwindow_memorysearch::update()
246 runemufn([msearch
, &ret
, &addr_count
, typecode
, hexmode
]() {
247 addr_count
= msearch
->get_candidate_count();
248 if(addr_count
<= CANDIDATE_LIMIT
) {
249 std::list
<uint32_t> addrs
= msearch
->get_candidates();
250 for(auto i
: addrs
) {
251 std::ostringstream row
;
252 row
<< hexformat_address(i
) << " ";
254 case 0: row
<< format_number_signed(memory_read_byte(i
), hexmode
); break;
255 case 1: row
<< format_number_unsigned(memory_read_byte(i
), hexmode
); break;
256 case 2: row
<< format_number_signed(memory_read_word(i
), hexmode
); break;
257 case 3: row
<< format_number_unsigned(memory_read_word(i
), hexmode
); break;
258 case 4: row
<< format_number_signed(memory_read_dword(i
), hexmode
); break;
259 case 5: row
<< format_number_unsigned(memory_read_dword(i
), hexmode
); break;
260 case 6: row
<< format_number_signed(memory_read_qword(i
), hexmode
); break;
261 case 7: row
<< format_number_unsigned(memory_read_qword(i
), hexmode
); break;
264 ret
= ret
+ row
.str();
267 ret
= "Too many candidates to display";
270 std::ostringstream x
;
271 x
<< addr_count
<< " " << ((addr_count
!= 1) ? "candidates" : "candidate");
272 count
->SetLabel(towxstring(x
.str()));
273 matches
->SetValue(towxstring(ret
));
275 update_queued
= false;
278 void wxwindow_memorysearch::on_button_click(wxCommandEvent
& e
)
280 wxwindow_memorysearch
* tmp
= this;
282 if(id
== wxID_RESET
) {
284 } else if(id
== wxID_UPDATE
) {
286 } else if(id
== wxID_TYPESELECT
) {
287 wxString c
= type
->GetValue();
288 for(unsigned i
= 0; i
< DATATYPES
; i
++)
289 if(c
== towxstring(datatypes
[i
]))
291 } else if(id
== wxID_HEX_SELECT
) {
292 hexmode
= hexmode2
->GetValue();
293 } else if(id
== wxID_BUTTONS_BASE
) {
297 case 0: valuesearch
<int8_t>(); break;
298 case 1: valuesearch
<uint8_t>(); break;
299 case 2: valuesearch
<int16_t>(); break;
300 case 3: valuesearch
<uint16_t>(); break;
301 case 4: valuesearch
<int32_t>(); break;
302 case 5: valuesearch
<uint32_t>(); break;
303 case 6: valuesearch
<int64_t>(); break;
304 case 7: valuesearch
<uint64_t>(); break;
306 } else if(id
> wxID_BUTTONS_BASE
&& id
< wxID_BUTTONS_BASE
+ 1 + PRIMITIVES
) {
307 int button
= id
- wxID_BUTTONS_BASE
- 1;
308 (msearch
->*(primitive_searches
[typecode
][button
]))();
313 template<typename T
> void wxwindow_memorysearch::valuesearch()
316 wxTextEntryDialog
* d
= new wxTextEntryDialog(this, wxT("Enter value to search for:"), wxT("Memory search"),
318 if(d
->ShowModal() == wxID_CANCEL
)
320 v
= tostdstring(d
->GetValue());
324 val2
= parse_value
<T
>(v
);
326 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
332 template<> void wxwindow_memorysearch::valuesearch2
<int8_t>(int8_t val
)
334 msearch
->byte_value(static_cast<uint8_t>(val
));
337 template<> void wxwindow_memorysearch::valuesearch2
<uint8_t>(uint8_t val
)
339 msearch
->byte_value(static_cast<uint8_t>(val
));
342 template<> void wxwindow_memorysearch::valuesearch2
<int16_t>(int16_t val
)
344 msearch
->word_value(static_cast<uint16_t>(val
));
347 template<> void wxwindow_memorysearch::valuesearch2
<uint16_t>(uint16_t val
)
349 msearch
->word_value(static_cast<uint16_t>(val
));
352 template<> void wxwindow_memorysearch::valuesearch2
<int32_t>(int32_t val
)
354 msearch
->dword_value(static_cast<uint32_t>(val
));
357 template<> void wxwindow_memorysearch::valuesearch2
<uint32_t>(uint32_t val
)
359 msearch
->dword_value(static_cast<uint32_t>(val
));
362 template<> void wxwindow_memorysearch::valuesearch2
<int64_t>(int64_t val
)
364 msearch
->qword_value(static_cast<uint64_t>(val
));
367 template<> void wxwindow_memorysearch::valuesearch2
<uint64_t>(uint64_t val
)
369 msearch
->qword_value(static_cast<uint64_t>(val
));
372 void wxwindow_memorysearch_display()
378 mwatch
= new wxwindow_memorysearch();