3 #include <wx/control.h>
4 #include <wx/combobox.h>
6 #include "core/dispatch.hpp"
7 #include "core/instance.hpp"
8 #include "core/instance-map.hpp"
9 #include "core/memorymanip.hpp"
10 #include "core/memorywatch.hpp"
11 #include "core/project.hpp"
12 #include "core/ui-services.hpp"
13 #include "library/hex.hpp"
14 #include "library/string.hpp"
15 #include "library/memorysearch.hpp"
16 #include "library/int24.hpp"
17 #include "library/zip.hpp"
19 #include "platform/wxwidgets/loadsave.hpp"
20 #include "platform/wxwidgets/platform.hpp"
21 #include "platform/wxwidgets/scrollbar.hpp"
22 #include "platform/wxwidgets/textrender.hpp"
28 #define wxID_RESET (wxID_HIGHEST + 1)
29 #define wxID_UPDATE (wxID_HIGHEST + 2)
30 #define wxID_TYPESELECT (wxID_HIGHEST + 3)
31 #define wxID_HEX_SELECT (wxID_HIGHEST + 4)
32 #define wxID_ADD (wxID_HIGHEST + 5)
33 #define wxID_SET_REGIONS (wxID_HIGHEST + 6)
34 #define wxID_AUTOUPDATE (wxID_HIGHEST + 7)
35 #define wxID_DISQUALIFY (wxID_HIGHEST + 8)
36 #define wxID_POKE (wxID_HIGHEST + 9)
37 #define wxID_SHOW_HEXEDITOR (wxID_HIGHEST + 10)
38 #define wxID_MENU_SAVE_PREVMEM (wxID_HIGHEST + 11)
39 #define wxID_MENU_SAVE_SET (wxID_HIGHEST + 12)
40 #define wxID_MENU_SAVE_ALL (wxID_HIGHEST + 13)
41 #define wxID_MENU_LOAD (wxID_HIGHEST + 14)
42 #define wxID_MENU_UNDO (wxID_HIGHEST + 15)
43 #define wxID_MENU_REDO (wxID_HIGHEST + 16)
44 #define wxID_MENU_DUMP_CANDIDATES (wxID_HIGHEST + 17)
45 #define wxID_BUTTONS_BASE (wxID_HIGHEST + 128)
48 #define CANDIDATE_LIMIT 512
50 class wxwindow_memorysearch
;
51 memory_search
* wxwindow_memorysearch_active();
55 unsigned UNDOHISTORY_MAXSIZE
= 48;
56 struct _watch_properties
{
58 int type
; //0 => Unsigned, 1 => Signed, 2 => Float.
60 } watch_properties
[] = {
75 instance_map
<wxwindow_memorysearch
> mwatch
;
77 const char* datatypes
[] = {
92 typedef void (wxwindow_memorysearch::*search_fn_t
)();
97 search_fn_t searches
[DATATYPES
];
100 template<typename T
> std::string
format_number_signed(T val
, bool hex
);
101 template<typename T
> std::string
format_number_unsigned(T val
, bool hex
);
103 template<typename T
> std::string
format_number_signedh(T val
, unsigned hwidth
, bool hex
)
105 std::ostringstream x
;
108 x
<< "+" << std::setfill('0') << std::setw(hwidth
) << std::hex
<<
109 static_cast<uint64_t>(val
);
112 uint64_t y
= static_cast<uint64_t>(y2
);
113 x
<< "-" << std::setfill('0') << std::setw(hwidth
) << std::hex
<< (~y
+ 1);
116 x
<< static_cast<int64_t>(val
);
120 template<typename T
> std::string
format_number_unsignedh(T val
, unsigned hwidth
, bool hex
)
122 std::ostringstream x
;
124 x
<< std::setfill('0') << std::setw(hwidth
) << std::hex
<< static_cast<uint64_t>(val
);
126 x
<< static_cast<uint64_t>(val
);
130 template<> std::string format_number_signed
<uint8_t>(uint8_t val
, bool hex
)
132 return format_number_signedh(static_cast<int8_t>(val
), 2, hex
);
135 template<> std::string format_number_signed
<uint16_t>(uint16_t val
, bool hex
)
137 return format_number_signedh(static_cast<int16_t>(val
), 4, hex
);
140 template<> std::string format_number_signed
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
142 return format_number_signedh((int32_t)(uint32_t)(val
), 6, hex
);
145 template<> std::string format_number_signed
<uint32_t>(uint32_t val
, bool hex
)
147 return format_number_signedh(static_cast<int32_t>(val
), 8, hex
);
150 template<> std::string format_number_signed
<uint64_t>(uint64_t val
, bool hex
)
152 return format_number_signedh(static_cast<int64_t>(val
), 16, hex
);
155 template<> std::string format_number_unsigned
<uint8_t>(uint8_t val
, bool hex
)
157 return format_number_unsignedh(val
, 2, hex
);
160 template<> std::string format_number_unsigned
<uint16_t>(uint16_t val
, bool hex
)
162 return format_number_unsignedh(val
, 4, hex
);
165 template<> std::string format_number_unsigned
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
167 return format_number_unsignedh(val
, 6, hex
);
170 template<> std::string format_number_unsigned
<uint32_t>(uint32_t val
, bool hex
)
172 return format_number_unsignedh(val
, 8, hex
);
175 template<> std::string format_number_unsigned
<uint64_t>(uint64_t val
, bool hex
)
177 return format_number_unsignedh(val
, 16, hex
);
180 std::string
format_number_float(double val
)
182 return (stringfmt() << val
).str();
186 class wxwindow_memorysearch_vmasel
: public wxDialog
189 wxwindow_memorysearch_vmasel(wxWindow
* p
, emulator_instance
& _inst
, const std::set
<std::string
>& enabled
);
190 bool ShouldPreventAppExit() const;
191 std::set
<std::string
> get_vmas();
192 void on_ok(wxCommandEvent
& e
);
193 void on_cancel(wxCommandEvent
& e
);
195 emulator_instance
& inst
;
196 std::set
<std::string
> vmas
;
197 std::vector
<wxCheckBox
*> checkboxes
;
202 wxwindow_memorysearch_vmasel::wxwindow_memorysearch_vmasel(wxWindow
* p
, emulator_instance
& _inst
,
203 const std::set
<std::string
>& enabled
)
204 : wxDialog(p
, wxID_ANY
, towxstring("lsnes: Select enabled regions"), wxDefaultPosition
, wxSize(300, -1)),
208 auto i
= inst
.memory
->get_regions();
210 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(i
.size() + 1, 1, 0, 0);
213 if(j
->readonly
|| j
->special
)
216 top_s
->Add(t
= new wxCheckBox(this, wxID_ANY
, towxstring(j
->name
)), 0, wxGROW
);
217 if(enabled
.count(j
->name
))
219 checkboxes
.push_back(t
);
221 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
222 pbutton_s
->AddStretchSpacer();
223 pbutton_s
->Add(ok
= new wxButton(this, wxID_ANY
, wxT("Ok")), 0, wxGROW
);
224 pbutton_s
->Add(cancel
= new wxButton(this, wxID_ANY
, wxT("Cancel")), 0, wxGROW
);
225 ok
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
226 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_ok
), NULL
, this);
227 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
228 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_cancel
), NULL
, this);
229 top_s
->Add(pbutton_s
);
231 pbutton_s
->SetSizeHints(this);
232 top_s
->SetSizeHints(this);
236 bool wxwindow_memorysearch_vmasel::ShouldPreventAppExit() const
241 std::set
<std::string
> wxwindow_memorysearch_vmasel::get_vmas()
246 void wxwindow_memorysearch_vmasel::on_ok(wxCommandEvent
& e
)
249 for(auto i
: checkboxes
)
251 vmas
.insert(tostdstring(i
->GetLabel()));
255 void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent
& e
)
258 EndModal(wxID_CANCEL
);
262 class wxwindow_memorysearch
: public wxFrame
265 class panel
: public text_framebuffer_panel
268 panel(wxwindow_memorysearch
* parent
, emulator_instance
& _inst
);
269 void set_selection(uint64_t first
, uint64_t last
);
270 void get_selection(uint64_t& first
, uint64_t& last
);
272 void prepare_paint();
274 emulator_instance
& inst
;
275 wxwindow_memorysearch
* parent
;
279 wxwindow_memorysearch(emulator_instance
& _inst
);
280 ~wxwindow_memorysearch();
281 bool ShouldPreventAppExit() const;
282 void on_close(wxCloseEvent
& e
);
283 void on_button_click(wxCommandEvent
& e
);
285 void on_mousedrag(wxMouseEvent
& e
);
286 void on_mouse(wxMouseEvent
& e
);
287 emulator_instance
& inst
;
289 template<void(memory_search::*sfn
)()> void search_0();
290 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void search_1();
291 template<typename T
> void _do_poke_addr(uint64_t addr
);
292 template<typename T
> std::string
_do_format_signed(uint64_t addr
, bool hex
, bool old
)
295 return format_number_signed
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
297 return format_number_signed
<T
>(inst
.memory
->read
<T
>(addr
), hex
);
299 template<typename T
> std::string
_do_format_unsigned(uint64_t addr
, bool hex
, bool old
)
302 return format_number_unsigned
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
304 return format_number_unsigned
<T
>(inst
.memory
->read
<T
>(addr
), hex
);
306 template<typename T
> std::string
_do_format_float(uint64_t addr
, bool hex
, bool old
)
309 return format_number_float(msearch
->v_readold
<T
>(addr
));
311 return format_number_float(inst
.memory
->read
<T
>(addr
));
313 void dump_candidates_text();
315 friend memory_search
* wxwindow_memorysearch_active(emulator_instance
& inst
);
317 template<typename T
> T
promptvalue(bool& bad
);
319 memory_search
* msearch
;
320 void on_mouse0(wxMouseEvent
& e
, bool polarity
);
322 void on_mouse2(wxMouseEvent
& e
);
323 void handle_undo_redo(bool redo
);
325 void handle_save(memory_search::savestate_type type
);
327 std::string
format_address(uint64_t addr
);
332 wxCheckBox
* hexmode2
;
333 wxCheckBox
* autoupdate
;
334 std::map
<uint64_t, uint64_t> addresses
;
336 uint64_t drag_startline
;
343 std::set
<std::string
> vmas_enabled
;
344 std::map
<std::string
, std::pair
<uint64_t, uint64_t>> vma_info
;
345 wxMenuItem
* undoitem
;
346 wxMenuItem
* redoitem
;
347 std::list
<std::vector
<char>> undohistory
;
348 std::list
<std::vector
<char>> redohistory
;
351 std::string
wxwindow_memorysearch::format_address(uint64_t addr
)
353 for(auto i
: vma_info
) {
354 if(i
.second
.first
<= addr
&& i
.second
.first
+ i
.second
.second
> addr
) {
357 uint64_t t
= i
.second
.second
;
358 while(t
> 0x10) { hcount
++; t
>>= 4; }
359 return (stringfmt() << i
.first
<< "+" << std::hex
<< std::setw(hcount
) << std::setfill('0')
360 << (addr
- i
.second
.first
)).str();
364 return hex::to(addr
);
369 typedef void (wxwindow_memorysearch::*pokefn_t
)(uint64_t);
371 &wxwindow_memorysearch::_do_poke_addr
<int8_t>,
372 &wxwindow_memorysearch::_do_poke_addr
<uint8_t>,
373 &wxwindow_memorysearch::_do_poke_addr
<int16_t>,
374 &wxwindow_memorysearch::_do_poke_addr
<uint16_t>,
375 &wxwindow_memorysearch::_do_poke_addr
<ss_int24_t
>,
376 &wxwindow_memorysearch::_do_poke_addr
<ss_uint24_t
>,
377 &wxwindow_memorysearch::_do_poke_addr
<int32_t>,
378 &wxwindow_memorysearch::_do_poke_addr
<uint32_t>,
379 &wxwindow_memorysearch::_do_poke_addr
<int64_t>,
380 &wxwindow_memorysearch::_do_poke_addr
<uint64_t>,
381 &wxwindow_memorysearch::_do_poke_addr
<float>,
382 &wxwindow_memorysearch::_do_poke_addr
<double>,
385 typedef std::string (wxwindow_memorysearch::*displayfn_t
)(uint64_t, bool hexmode
, bool old
);
386 displayfn_t displays
[] = {
387 &wxwindow_memorysearch::_do_format_signed
<uint8_t>,
388 &wxwindow_memorysearch::_do_format_unsigned
<uint8_t>,
389 &wxwindow_memorysearch::_do_format_signed
<uint16_t>,
390 &wxwindow_memorysearch::_do_format_unsigned
<uint16_t>,
391 &wxwindow_memorysearch::_do_format_signed
<ss_uint24_t
>,
392 &wxwindow_memorysearch::_do_format_unsigned
<ss_uint24_t
>,
393 &wxwindow_memorysearch::_do_format_signed
<uint32_t>,
394 &wxwindow_memorysearch::_do_format_unsigned
<uint32_t>,
395 &wxwindow_memorysearch::_do_format_signed
<uint64_t>,
396 &wxwindow_memorysearch::_do_format_unsigned
<uint64_t>,
397 &wxwindow_memorysearch::_do_format_float
<float>,
398 &wxwindow_memorysearch::_do_format_float
<double>,
401 struct searchtype searchtbl
[] = {
404 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
405 &memory_search::s_value
<uint8_t>>,
406 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
407 &memory_search::s_value
<uint8_t>>,
408 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
409 &memory_search::s_value
<uint16_t>>,
410 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
411 &memory_search::s_value
<uint16_t>>,
412 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
413 &memory_search::s_value
<ss_uint24_t
>>,
414 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
415 &memory_search::s_value
<ss_uint24_t
>>,
416 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
417 &memory_search::s_value
<uint32_t>>,
418 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
419 &memory_search::s_value
<uint32_t>>,
420 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
421 &memory_search::s_value
<uint64_t>>,
422 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
423 &memory_search::s_value
<uint64_t>>,
424 &wxwindow_memorysearch::search_1
<float, float,
425 &memory_search::s_value
<float>>,
426 &wxwindow_memorysearch::search_1
<double, double,
427 &memory_search::s_value
<double>>
431 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
432 &memory_search::s_difference
<uint8_t>>,
433 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
434 &memory_search::s_difference
<uint8_t>>,
435 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
436 &memory_search::s_difference
<uint16_t>>,
437 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
438 &memory_search::s_difference
<uint16_t>>,
439 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
440 &memory_search::s_difference
<ss_uint24_t
>>,
441 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
442 &memory_search::s_difference
<ss_uint24_t
>>,
443 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
444 &memory_search::s_difference
<uint32_t>>,
445 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
446 &memory_search::s_difference
<uint32_t>>,
447 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
448 &memory_search::s_difference
<uint64_t>>,
449 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
450 &memory_search::s_difference
<uint64_t>>,
451 &wxwindow_memorysearch::search_1
<float, float,
452 &memory_search::s_difference
<float>>,
453 &wxwindow_memorysearch::search_1
<double, double,
454 &memory_search::s_difference
<double>>
458 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int8_t>>,
459 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint8_t>>,
460 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int16_t>>,
461 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint16_t>>,
462 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_int24_t
>>,
463 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_uint24_t
>>,
464 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int32_t>>,
465 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint32_t>>,
466 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int64_t>>,
467 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint64_t>>,
468 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
469 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
473 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int8_t>>,
474 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint8_t>>,
475 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int16_t>>,
476 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint16_t>>,
477 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_int24_t
>>,
478 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_uint24_t
>>,
479 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int32_t>>,
480 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint32_t>>,
481 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int64_t>>,
482 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint64_t>>,
483 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
484 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
488 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int8_t>>,
489 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint8_t>>,
490 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int16_t>>,
491 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint16_t>>,
492 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_int24_t
>>,
493 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_uint24_t
>>,
494 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int32_t>>,
495 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint32_t>>,
496 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int64_t>>,
497 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint64_t>>,
498 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<float>>,
499 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<double>>
503 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int8_t>>,
504 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint8_t>>,
505 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int16_t>>,
506 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint16_t>>,
507 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_int24_t
>>,
508 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_uint24_t
>>,
509 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int32_t>>,
510 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint32_t>>,
511 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int64_t>>,
512 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint64_t>>,
513 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<float>>,
514 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<double>>
518 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int8_t>>,
519 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint8_t>>,
520 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int16_t>>,
521 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint16_t>>,
522 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_int24_t
>>,
523 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_uint24_t
>>,
524 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int32_t>>,
525 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint32_t>>,
526 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int64_t>>,
527 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint64_t>>,
528 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
529 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
533 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int8_t>>,
534 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint8_t>>,
535 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int16_t>>,
536 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint16_t>>,
537 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_int24_t
>>,
538 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_uint24_t
>>,
539 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int32_t>>,
540 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint32_t>>,
541 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int64_t>>,
542 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint64_t>>,
543 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
544 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
548 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
549 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
550 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
551 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
552 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_int24_t
>>,
553 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_uint24_t
>>,
554 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
555 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
556 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
557 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
558 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
559 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
563 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
564 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
565 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
566 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
567 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_int24_t
>>,
568 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_uint24_t
>>,
569 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
570 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
571 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
572 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
573 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
574 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
578 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
579 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
580 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
581 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
582 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_int24_t
>>,
583 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_uint24_t
>>,
584 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
585 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
586 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
587 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
588 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
589 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
593 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
594 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
595 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
596 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
597 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_int24_t
>>,
598 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_uint24_t
>>,
599 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
600 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
601 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
602 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
603 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
604 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
608 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
609 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
610 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
611 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
612 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
613 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
614 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
615 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
616 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
617 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
618 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
619 &wxwindow_memorysearch::search_0
<&memory_search::update
>
625 wxwindow_memorysearch::wxwindow_memorysearch(emulator_instance
& _inst
)
626 : wxFrame(NULL
, wxID_ANY
, wxT("lsnes: Memory Search"), wxDefaultPosition
, wxSize(-1, -1),
627 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
), inst(_inst
)
633 Connect(wxEVT_CLOSE_WINDOW
, wxCloseEventHandler(wxwindow_memorysearch::on_close
));
634 msearch
= new memory_search(*inst
.memory
);
636 wxFlexGridSizer
* toplevel
= new wxFlexGridSizer(4, 1, 0, 0);
639 wxBoxSizer
* buttons
= new wxBoxSizer(wxHORIZONTAL
);
640 buttons
->Add(tmp
= new wxButton(this, wxID_RESET
, wxT("Reset")), 0, wxGROW
);
641 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
643 buttons
->Add(new wxStaticText(this, wxID_ANY
, wxT("Data type:")), 0, wxGROW
);
644 wxString _datatypes
[DATATYPES
];
645 for(size_t i
= 0; i
< DATATYPES
; i
++)
646 _datatypes
[i
] = towxstring(datatypes
[i
]);
647 buttons
->Add(type
= new wxComboBox(this, wxID_TYPESELECT
, _datatypes
[typecode
], wxDefaultPosition
,
648 wxDefaultSize
, DATATYPES
, _datatypes
, wxCB_READONLY
), 0,
650 type
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
651 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
652 buttons
->Add(hexmode2
= new wxCheckBox(this, wxID_HEX_SELECT
, wxT("Hex display")), 0, wxGROW
);
653 buttons
->Add(autoupdate
= new wxCheckBox(this, wxID_AUTOUPDATE
, wxT("Update automatically")), 0, wxGROW
);
654 autoupdate
->SetValue(true);
655 hexmode2
->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED
,
656 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
657 toplevel
->Add(buttons
);
659 wxFlexGridSizer
* searches
= new wxFlexGridSizer(0, 6, 0, 0);
660 for(unsigned j
= 0; j
< sizeof(searchtbl
)/sizeof(searchtbl
[0]); j
++) {
661 std::string name
= searchtbl
[j
].name
;
662 searches
->Add(tmp
= new wxButton(this, wxID_BUTTONS_BASE
+ j
, towxstring(name
)), 1, wxGROW
);
663 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
664 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
666 toplevel
->Add(searches
);
668 toplevel
->Add(count
= new wxStaticText(this, wxID_ANY
, wxT("XXXXXX candidates")), 0, wxGROW
);
669 wxBoxSizer
* matchesb
= new wxBoxSizer(wxHORIZONTAL
);
670 matchesb
->Add(matches
= new panel(this, inst
), 1, wxGROW
);
671 matchesb
->Add(scroll
= new scroll_bar(this, wxID_ANY
, true), 0, wxGROW
);
672 toplevel
->Add(matchesb
, 1, wxGROW
);
674 scroll
->set_page_size(matches
->get_characters().second
);
676 for(auto i
: inst
.memory
->get_regions()) {
677 if(memory_search::searchable_region(i
))
678 vmas_enabled
.insert(i
->name
);
679 vma_info
[i
->name
] = std::make_pair(i
->base
, i
->size
);
682 wxMenuBar
* menubar
= new wxMenuBar();
684 wxMenu
* filemenu
= new wxMenu();
685 filemenu
->Append(wxID_MENU_DUMP_CANDIDATES
, wxT("Dump candidates..."));
686 filemenu
->AppendSeparator();
687 filemenu
->Append(wxID_MENU_SAVE_PREVMEM
, wxT("Save previous memory..."));
688 filemenu
->Append(wxID_MENU_SAVE_SET
, wxT("Save set of addresses..."));
689 filemenu
->Append(wxID_MENU_SAVE_ALL
, wxT("Save previous memory and set of addresses..."));
690 filemenu
->AppendSeparator();
691 filemenu
->Append(wxID_MENU_LOAD
, wxT("Load save..."));
692 menubar
->Append(filemenu
, wxT("File"));
693 wxMenu
* editmenu
= new wxMenu();
694 undoitem
= editmenu
->Append(wxID_UNDO
, wxT("Undo"));
695 redoitem
= editmenu
->Append(wxID_REDO
, wxT("Redo"));
696 undoitem
->Enable(false);
697 redoitem
->Enable(false);
698 menubar
->Append(editmenu
, wxT("Edit"));
699 Connect(wxID_MENU_DUMP_CANDIDATES
, wxEVT_COMMAND_MENU_SELECTED
,
700 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
701 Connect(wxID_MENU_SAVE_PREVMEM
, wxEVT_COMMAND_MENU_SELECTED
,
702 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
703 Connect(wxID_MENU_SAVE_SET
, wxEVT_COMMAND_MENU_SELECTED
,
704 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
705 Connect(wxID_MENU_SAVE_ALL
, wxEVT_COMMAND_MENU_SELECTED
,
706 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
707 Connect(wxID_MENU_LOAD
, wxEVT_COMMAND_MENU_SELECTED
,
708 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
709 Connect(wxID_UNDO
, wxEVT_COMMAND_MENU_SELECTED
,
710 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
711 Connect(wxID_REDO
, wxEVT_COMMAND_MENU_SELECTED
,
712 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
716 matches
->Connect(wxEVT_LEFT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
717 matches
->Connect(wxEVT_LEFT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
718 matches
->Connect(wxEVT_MIDDLE_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
719 matches
->Connect(wxEVT_MIDDLE_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
720 matches
->Connect(wxEVT_RIGHT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
721 matches
->Connect(wxEVT_RIGHT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
722 matches
->Connect(wxEVT_MOTION
, wxMouseEventHandler(wxwindow_memorysearch::on_mousedrag
), NULL
, this);
723 matches
->Connect(wxEVT_MOUSEWHEEL
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
724 scroll
->set_handler([this](scroll_bar
& s
) { this->matches
->request_paint(); });
726 toplevel
->SetSizeHints(this);
733 wxwindow_memorysearch::panel::panel(wxwindow_memorysearch
* _parent
, emulator_instance
& _inst
)
734 : text_framebuffer_panel(_parent
, 40, 25, wxID_ANY
, NULL
), inst(_inst
)
741 void wxwindow_memorysearch::panel::prepare_paint()
744 uint64_t first
= parent
->scroll
->get_position();
745 auto ssize
= get_characters();
746 uint64_t last
= first
+ ssize
.second
;
747 std::vector
<std::string
> lines
;
748 lines
.reserve(ssize
.second
);
749 std::map
<uint64_t, uint64_t> addrs
;
750 auto* ms
= parent
->msearch
;
752 bool toomany
= false;
753 auto _parent
= parent
;
754 inst
.iqueue
->run([&toomany
, &first
, &last
, ms
, &lines
, &addrs
, &addr_count
, _parent
]() {
755 addr_count
= ms
->get_candidate_count();
756 if(last
> addr_count
) {
757 uint64_t delta
= last
- addr_count
;
766 if(addr_count
<= CANDIDATE_LIMIT
) {
767 std::list
<uint64_t> addrs2
= ms
->get_candidates();
769 for(auto i
: addrs2
) {
770 std::string row
= _parent
->format_address(i
) + " ";
771 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, false);
773 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, true);
775 if(j
>= first
&& j
< last
)
776 lines
.push_back(row
);
780 lines
.push_back("Too many candidates to display");
784 std::swap(parent
->addresses
, addrs
);
786 std::ostringstream x
;
787 x
<< addr_count
<< " " << ((addr_count
!= 1) ? "candidates" : "candidate");
788 parent
->count
->SetLabel(towxstring(x
.str()));
791 for(unsigned i
= 0; i
< lines
.size(); i
++) {
792 bool sel
= (first
+ i
) >= first_sel
&& (first
+ i
) < last_sel
;
793 write(lines
[i
], 0, 0, i
, sel
? 0xFFFFFF : 0, sel
? 0 : 0xFFFFFF);
801 parent
->toomany
= toomany
;
802 parent
->scroll
->set_range(toomany
? 0 : addr_count
);
805 void wxwindow_memorysearch::panel::set_selection(uint64_t first
, uint64_t last
)
812 void wxwindow_memorysearch::panel::get_selection(uint64_t& first
, uint64_t& last
)
818 wxwindow_memorysearch::~wxwindow_memorysearch()
824 bool wxwindow_memorysearch::ShouldPreventAppExit() const
829 void wxwindow_memorysearch::dump_candidates_text()
832 std::string filename
= choose_file_save(this, "Dump memory search",
833 UI_get_project_otherpath(inst
), filetype_textfile
);
834 std::ofstream
out(filename
);
836 inst
.iqueue
->run([ms
, this, &out
]() {
837 std::list
<uint64_t> addrs2
= ms
->get_candidates();
838 for(auto i
: addrs2
) {
839 std::string row
= format_address(i
) + " ";
840 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, false);
842 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, true);
844 out
<< row
<< std::endl
;
848 throw std::runtime_error("Can't write save file");
849 } catch(canceled_exception
& e
) {
850 } catch(std::exception
& e
) {
851 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
856 void wxwindow_memorysearch::handle_save(memory_search::savestate_type type
)
859 std::vector
<char> state
;
860 msearch
->savestate(state
, type
);
861 std::string filename
= choose_file_save(this, "Save memory search",
862 UI_get_project_otherpath(inst
), filetype_memorysearch
);
863 std::ofstream
out(filename
, std::ios::binary
);
864 out
.write(&state
[0], state
.size());
866 throw std::runtime_error("Can't write save file");
867 } catch(canceled_exception
& e
) {
868 } catch(std::exception
& e
) {
869 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
874 void wxwindow_memorysearch::handle_load()
877 std::string filename
= choose_file_load(this, "Load memory search",
878 UI_get_project_otherpath(inst
), filetype_memorysearch
);
879 std::vector
<char> state
= zip::readrel(filename
, "");
881 msearch
->loadstate(state
);
883 } catch(canceled_exception
& e
) {
884 } catch(std::exception
& e
) {
885 show_message_ok(this, "Load error", std::string(e
.what()), wxICON_WARNING
);
890 void wxwindow_memorysearch::handle_undo_redo(bool redo
)
892 std::list
<std::vector
<char>>& a
= *(redo
? &redohistory
: &undohistory
);
893 std::list
<std::vector
<char>>& b
= *(redo
? &undohistory
: &redohistory
);
895 show_message_ok(this, "Undo/Redo error", "Can't find state to undo/redo to", wxICON_WARNING
);
900 std::vector
<char> state
;
901 msearch
->savestate(state
, memory_search::ST_SET
);
904 msearch
->loadstate(a
.back());
906 } catch(std::exception
& e
) {
909 show_message_ok(this, "Undo/Redo error", std::string(e
.what()), wxICON_WARNING
);
912 undoitem
->Enable(undohistory
.size());
913 redoitem
->Enable(redohistory
.size());
917 void wxwindow_memorysearch::push_undo()
920 std::vector
<char> state
;
921 msearch
->savestate(state
, memory_search::ST_SET
);
922 undohistory
.push_back(state
);
923 if(undohistory
.size() > UNDOHISTORY_MAXSIZE
)
924 undohistory
.pop_front();
926 undoitem
->Enable(undohistory
.size());
927 redoitem
->Enable(redohistory
.size());
932 void wxwindow_memorysearch::on_mouse(wxMouseEvent
& e
)
935 if(e
.RightUp() || (e
.LeftUp() && e
.ControlDown()))
937 else if(e
.LeftDown())
944 if(e
.ShiftDown() && e
.ControlDown())
946 scroll
->apply_wheel(e
.GetWheelRotation(), e
.GetWheelDelta(), speed
);
949 void wxwindow_memorysearch::on_mouse0(wxMouseEvent
& e
, bool polarity
)
952 dragging
= polarity
&& !toomany
;
956 uint64_t first
= scroll
->get_position();
957 drag_startline
= first
+ e
.GetY() / matches
->get_cell().second
;
958 } else if(mpx
== e
.GetX() && mpy
== e
.GetY()) {
959 matches
->set_selection(0, 0);
963 void wxwindow_memorysearch::on_mousedrag(wxMouseEvent
& e
)
968 uint64_t first
= scroll
->get_position();
969 uint64_t linenow
= first
+ e
.GetY() / matches
->get_cell().second
;
970 if(drag_startline
< linenow
)
971 matches
->set_selection(drag_startline
, linenow
+ 1);
973 matches
->set_selection(linenow
, drag_startline
+ 1);
976 void wxwindow_memorysearch::on_mouse2(wxMouseEvent
& e
)
981 uint64_t selcount
= 0;
983 matches
->get_selection(start
, end
);
984 some_selected
= (start
< end
);
986 uint64_t first
= scroll
->get_position();
987 act_line
= first
+ e
.GetY() / matches
->get_cell().second
;
988 if(addresses
.count(act_line
)) {
989 some_selected
= true;
993 menu
.Append(wxID_ADD
, wxT("Add watch..."))->Enable(some_selected
);
994 menu
.Append(wxID_SHOW_HEXEDITOR
, wxT("Select in hex editor"))->Enable(selcount
== 1 &&
995 wxeditor_hexeditor_available(inst
));
996 menu
.Append(wxID_POKE
, wxT("Poke..."))->Enable(selcount
== 1);
997 menu
.AppendSeparator();
998 menu
.Append(wxID_DISQUALIFY
, wxT("Disqualify"))->Enable(some_selected
);
999 menu
.AppendSeparator();
1000 menu
.Append(wxID_UPDATE
, wxT("Update"));
1001 menu
.Append(wxID_SET_REGIONS
, wxT("Enabled VMAs"));
1002 menu
.Connect(wxEVT_COMMAND_MENU_SELECTED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
1007 void wxwindow_memorysearch::on_close(wxCloseEvent
& e
)
1013 void wxwindow_memorysearch::auto_update()
1016 if(autoupdate
->GetValue())
1020 void wxwindow_memorysearch::update()
1022 matches
->request_paint();
1025 void wxwindow_memorysearch::on_button_click(wxCommandEvent
& e
)
1029 if(id
== wxID_RESET
) {
1032 //Update all VMA info too.
1033 for(auto i
: inst
.memory
->get_regions()) {
1034 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
1035 msearch
->dq_range(i
->base
, i
->last_address());
1036 vma_info
[i
->name
] = std::make_pair(i
->base
, i
->size
);
1038 wxeditor_hexeditor_update(inst
);
1039 } else if(id
== wxID_UPDATE
) {
1041 } else if(id
== wxID_TYPESELECT
) {
1042 wxString c
= type
->GetValue();
1043 for(unsigned i
= 0; i
< DATATYPES
; i
++)
1044 if(c
== towxstring(datatypes
[i
]))
1046 } else if(id
== wxID_HEX_SELECT
) {
1047 hexmode
= hexmode2
->GetValue();
1048 } else if(id
== wxID_ADD
) {
1049 uint64_t start
, end
;
1050 matches
->get_selection(start
, end
);
1055 for(uint64_t r
= start
; r
< end
; r
++) {
1056 if(!addresses
.count(r
))
1058 uint64_t addr
= addresses
[r
];
1060 std::string n
= pick_text(this, "Name for watch", (stringfmt()
1061 << "Enter name for watch at 0x" << std::hex
<< addr
<< ":").str());
1065 e
.expr
= (stringfmt() << addr
).str();
1066 bool is_hex
= hexmode2
->GetValue();
1067 e
.bytes
= watch_properties
[typecode
].len
;
1068 e
.signed_flag
= !is_hex
&& (watch_properties
[typecode
].type
== 1);
1069 e
.float_flag
= (watch_properties
[typecode
].type
== 2);
1070 if(e
.float_flag
) is_hex
= false;
1071 e
.format
= is_hex
? watch_properties
[typecode
].hformat
: "";
1072 auto i
= inst
.memory
->get_regions();
1075 if(addr
>= j
->base
&& addr
< j
->base
+ j
->size
)
1076 endianess
= j
->endian
;
1078 e
.endianess
= endianess
;
1079 inst
.iqueue
->run([n
, &e
]() { CORE().mwatch
->set(n
, e
); });
1080 } catch(canceled_exception
& e
) {
1083 matches
->set_selection(0, 0);
1084 } else if(id
== wxID_DISQUALIFY
) {
1085 uint64_t start
, end
;
1086 matches
->get_selection(start
, end
);
1092 for(uint64_t r
= start
; r
< end
; r
++) {
1093 if(!addresses
.count(r
))
1095 uint64_t addr
= addresses
[r
];
1097 inst
.iqueue
->run([addr
, ms
]() { ms
->dq_range(addr
, addr
); });
1099 matches
->set_selection(0, 0);
1100 wxeditor_hexeditor_update(inst
);
1101 } else if(id
== wxID_SET_REGIONS
) {
1102 wxwindow_memorysearch_vmasel
* d
= new wxwindow_memorysearch_vmasel(this, inst
, vmas_enabled
);
1103 if(d
->ShowModal() == wxID_OK
)
1104 vmas_enabled
= d
->get_vmas();
1111 for(auto i
: inst
.memory
->get_regions())
1112 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
1113 msearch
->dq_range(i
->base
, i
->last_address());
1114 wxeditor_hexeditor_update(inst
);
1115 } else if(id
== wxID_POKE
) {
1116 uint64_t start
, end
;
1117 matches
->get_selection(start
, end
);
1122 for(uint64_t r
= start
; r
< end
; r
++) {
1123 if(!addresses
.count(r
))
1125 uint64_t addr
= addresses
[r
];
1127 (this->*(pokes
[typecode
]))(addr
);
1128 } catch(canceled_exception
& e
) {
1132 } else if(id
== wxID_SHOW_HEXEDITOR
) {
1133 uint64_t start
, end
;
1134 matches
->get_selection(start
, end
);
1139 for(uint64_t r
= start
; r
< end
; r
++) {
1140 if(!addresses
.count(r
))
1142 wxeditor_hexeditor_jumpto(inst
, addresses
[r
]);
1145 } else if(id
>= wxID_BUTTONS_BASE
&& id
< wxID_BUTTONS_BASE
+
1146 (ssize_t
)(sizeof(searchtbl
)/sizeof(searchtbl
[0]))) {
1147 int button
= id
- wxID_BUTTONS_BASE
;
1149 uint64_t old_count
= msearch
->get_candidate_count();
1150 (this->*(searchtbl
[button
].searches
[typecode
]))();
1151 uint64_t new_count
= msearch
->get_candidate_count();
1152 if(old_count
== new_count
) {
1153 undohistory
.pop_back(); //Shouldn't be undoable.
1154 undoitem
->Enable(undohistory
.size());
1156 wxeditor_hexeditor_update(inst
);
1157 } else if(id
== wxID_MENU_DUMP_CANDIDATES
) {
1158 dump_candidates_text();
1159 } else if(id
== wxID_MENU_SAVE_PREVMEM
) {
1160 handle_save(memory_search::ST_PREVMEM
);
1161 } else if(id
== wxID_MENU_SAVE_SET
) {
1162 handle_save(memory_search::ST_SET
);
1163 } else if(id
== wxID_MENU_SAVE_ALL
) {
1164 handle_save(memory_search::ST_ALL
);
1165 } else if(id
== wxID_MENU_LOAD
) {
1167 } else if(id
== wxID_UNDO
) {
1168 handle_undo_redo(false);
1169 } else if(id
== wxID_REDO
) {
1170 handle_undo_redo(true);
1175 template<typename T
> void wxwindow_memorysearch::_do_poke_addr(uint64_t addr
)
1178 T val
= msearch
->v_read
<T
>(addr
);
1181 v
= pick_text(this, "Poke value", (stringfmt() << "Enter value to poke to " << std::hex
<< "0x"
1182 << addr
).str(), (stringfmt() << val
).str(), false);
1183 val
= parse_value
<T
>(v
);
1184 } catch(canceled_exception
& e
) {
1187 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1190 msearch
->v_write
<T
>(addr
, val
);
1193 template<void(memory_search::*sfn
)()> void wxwindow_memorysearch::search_0()
1198 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void wxwindow_memorysearch::search_1()
1202 T val
= promptvalue
<T
>(bad
);
1205 (msearch
->*sfn
)(static_cast<T2
>(val
));
1208 template<typename T
> T
wxwindow_memorysearch::promptvalue(bool& bad
)
1212 wxTextEntryDialog
* d
= new wxTextEntryDialog(this, wxT("Enter value to search for:"), wxT("Memory search"),
1214 if(d
->ShowModal() == wxID_CANCEL
) {
1218 v
= tostdstring(d
->GetValue());
1222 val2
= parse_value
<T
>(v
);
1224 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1231 void wxwindow_memorysearch_display(emulator_instance
& inst
)
1234 auto e
= mwatch
.lookup(inst
);
1239 mwatch
.create(inst
)->Show();
1242 void wxwindow_memorysearch_update(emulator_instance
& inst
)
1244 auto e
= mwatch
.lookup(inst
);
1245 if(e
) e
->auto_update();
1248 memory_search
* wxwindow_memorysearch_active(emulator_instance
& inst
)
1250 auto e
= mwatch
.lookup(inst
);
1251 return e
? e
->msearch
: NULL
;