1 #include "core/dispatch.hpp"
2 #include "core/memorymanip.hpp"
3 #include "core/memorywatch.hpp"
4 #include "core/project.hpp"
5 #include "library/hex.hpp"
6 #include "library/string.hpp"
7 #include "library/memorysearch.hpp"
8 #include "library/int24.hpp"
9 #include "library/zip.hpp"
11 #include "platform/wxwidgets/loadsave.hpp"
12 #include "platform/wxwidgets/platform.hpp"
13 #include "platform/wxwidgets/scrollbar.hpp"
14 #include "platform/wxwidgets/textrender.hpp"
22 #include <wx/control.h>
23 #include <wx/combobox.h>
25 #define wxID_RESET (wxID_HIGHEST + 1)
26 #define wxID_UPDATE (wxID_HIGHEST + 2)
27 #define wxID_TYPESELECT (wxID_HIGHEST + 3)
28 #define wxID_HEX_SELECT (wxID_HIGHEST + 4)
29 #define wxID_ADD (wxID_HIGHEST + 5)
30 #define wxID_SET_REGIONS (wxID_HIGHEST + 6)
31 #define wxID_AUTOUPDATE (wxID_HIGHEST + 7)
32 #define wxID_DISQUALIFY (wxID_HIGHEST + 8)
33 #define wxID_POKE (wxID_HIGHEST + 9)
34 #define wxID_SHOW_HEXEDITOR (wxID_HIGHEST + 10)
35 #define wxID_MENU_SAVE_PREVMEM (wxID_HIGHEST + 11)
36 #define wxID_MENU_SAVE_SET (wxID_HIGHEST + 12)
37 #define wxID_MENU_SAVE_ALL (wxID_HIGHEST + 13)
38 #define wxID_MENU_LOAD (wxID_HIGHEST + 14)
39 #define wxID_MENU_UNDO (wxID_HIGHEST + 15)
40 #define wxID_MENU_REDO (wxID_HIGHEST + 16)
41 #define wxID_MENU_DUMP_CANDIDATES (wxID_HIGHEST + 17)
42 #define wxID_BUTTONS_BASE (wxID_HIGHEST + 128)
45 #define CANDIDATE_LIMIT 512
47 class wxwindow_memorysearch
;
48 memory_search
* wxwindow_memorysearch_active();
52 unsigned UNDOHISTORY_MAXSIZE
= 48;
53 struct _watch_properties
{
55 int type
; //0 => Unsigned, 1 => Signed, 2 => Float.
57 } watch_properties
[] = {
72 wxwindow_memorysearch
* mwatch
;
74 const char* datatypes
[] = {
89 typedef void (wxwindow_memorysearch::*search_fn_t
)();
94 search_fn_t searches
[DATATYPES
];
97 template<typename T
> std::string
format_number_signed(T val
, bool hex
);
98 template<typename T
> std::string
format_number_unsigned(T val
, bool hex
);
100 template<typename T
> std::string
format_number_signedh(T val
, unsigned hwidth
, bool hex
)
102 std::ostringstream x
;
105 x
<< "+" << std::setfill('0') << std::setw(hwidth
) << std::hex
<<
106 static_cast<uint64_t>(val
);
109 uint64_t y
= static_cast<uint64_t>(y2
);
110 x
<< "-" << std::setfill('0') << std::setw(hwidth
) << std::hex
<< (~y
+ 1);
113 x
<< static_cast<int64_t>(val
);
117 template<typename T
> std::string
format_number_unsignedh(T val
, unsigned hwidth
, bool hex
)
119 std::ostringstream x
;
121 x
<< std::setfill('0') << std::setw(hwidth
) << std::hex
<< static_cast<uint64_t>(val
);
123 x
<< static_cast<uint64_t>(val
);
127 template<> std::string format_number_signed
<uint8_t>(uint8_t val
, bool hex
)
129 return format_number_signedh(static_cast<int8_t>(val
), 2, hex
);
132 template<> std::string format_number_signed
<uint16_t>(uint16_t val
, bool hex
)
134 return format_number_signedh(static_cast<int16_t>(val
), 4, hex
);
137 template<> std::string format_number_signed
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
139 return format_number_signedh((int32_t)(uint32_t)(val
), 6, hex
);
142 template<> std::string format_number_signed
<uint32_t>(uint32_t val
, bool hex
)
144 return format_number_signedh(static_cast<int32_t>(val
), 8, hex
);
147 template<> std::string format_number_signed
<uint64_t>(uint64_t val
, bool hex
)
149 return format_number_signedh(static_cast<int64_t>(val
), 16, hex
);
152 template<> std::string format_number_unsigned
<uint8_t>(uint8_t val
, bool hex
)
154 return format_number_unsignedh(val
, 2, hex
);
157 template<> std::string format_number_unsigned
<uint16_t>(uint16_t val
, bool hex
)
159 return format_number_unsignedh(val
, 4, hex
);
162 template<> std::string format_number_unsigned
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
164 return format_number_unsignedh(val
, 6, hex
);
167 template<> std::string format_number_unsigned
<uint32_t>(uint32_t val
, bool hex
)
169 return format_number_unsignedh(val
, 8, hex
);
172 template<> std::string format_number_unsigned
<uint64_t>(uint64_t val
, bool hex
)
174 return format_number_unsignedh(val
, 16, hex
);
177 std::string
format_number_float(double val
)
179 return (stringfmt() << val
).str();
183 class wxwindow_memorysearch_vmasel
: public wxDialog
186 wxwindow_memorysearch_vmasel(wxWindow
* p
, const std::set
<std::string
>& enabled
);
187 bool ShouldPreventAppExit() const;
188 std::set
<std::string
> get_vmas();
189 void on_ok(wxCommandEvent
& e
);
190 void on_cancel(wxCommandEvent
& e
);
192 std::set
<std::string
> vmas
;
193 std::vector
<wxCheckBox
*> checkboxes
;
198 wxwindow_memorysearch_vmasel::wxwindow_memorysearch_vmasel(wxWindow
* p
, const std::set
<std::string
>& enabled
)
199 : wxDialog(p
, wxID_ANY
, towxstring("lsnes: Select enabled regions"), wxDefaultPosition
, wxSize(300, -1))
201 auto i
= lsnes_memory
.get_regions();
203 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(i
.size() + 1, 1, 0, 0);
206 if(j
->readonly
|| j
->special
)
209 top_s
->Add(t
= new wxCheckBox(this, wxID_ANY
, towxstring(j
->name
)), 0, wxGROW
);
210 if(enabled
.count(j
->name
))
212 checkboxes
.push_back(t
);
214 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
215 pbutton_s
->AddStretchSpacer();
216 pbutton_s
->Add(ok
= new wxButton(this, wxID_ANY
, wxT("Ok")), 0, wxGROW
);
217 pbutton_s
->Add(cancel
= new wxButton(this, wxID_ANY
, wxT("Cancel")), 0, wxGROW
);
218 ok
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
219 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_ok
), NULL
, this);
220 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
221 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_cancel
), NULL
, this);
222 top_s
->Add(pbutton_s
);
224 pbutton_s
->SetSizeHints(this);
225 top_s
->SetSizeHints(this);
229 bool wxwindow_memorysearch_vmasel::ShouldPreventAppExit() const
234 std::set
<std::string
> wxwindow_memorysearch_vmasel::get_vmas()
239 void wxwindow_memorysearch_vmasel::on_ok(wxCommandEvent
& e
)
241 for(auto i
: checkboxes
)
243 vmas
.insert(tostdstring(i
->GetLabel()));
247 void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent
& e
)
249 EndModal(wxID_CANCEL
);
253 class wxwindow_memorysearch
: public wxFrame
256 class panel
: public text_framebuffer_panel
259 panel(wxwindow_memorysearch
* parent
);
260 void set_selection(uint64_t first
, uint64_t last
);
261 void get_selection(uint64_t& first
, uint64_t& last
);
263 void prepare_paint();
265 wxwindow_memorysearch
* parent
;
269 wxwindow_memorysearch();
270 ~wxwindow_memorysearch();
271 bool ShouldPreventAppExit() const;
272 void on_close(wxCloseEvent
& e
);
273 void on_button_click(wxCommandEvent
& e
);
275 void on_mousedrag(wxMouseEvent
& e
);
276 void on_mouse(wxMouseEvent
& e
);
278 template<void(memory_search::*sfn
)()> void search_0();
279 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void search_1();
280 template<typename T
> void _do_poke_addr(uint64_t addr
);
281 template<typename T
> std::string
_do_format_signed(uint64_t addr
, bool hex
, bool old
)
284 return format_number_signed
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
286 return format_number_signed
<T
>(lsnes_memory
.read
<T
>(addr
), hex
);
288 template<typename T
> std::string
_do_format_unsigned(uint64_t addr
, bool hex
, bool old
)
291 return format_number_unsigned
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
293 return format_number_unsigned
<T
>(lsnes_memory
.read
<T
>(addr
), hex
);
295 template<typename T
> std::string
_do_format_float(uint64_t addr
, bool hex
, bool old
)
298 return format_number_float(msearch
->v_readold
<T
>(addr
));
300 return format_number_float(lsnes_memory
.read
<T
>(addr
));
302 void dump_candidates_text();
304 friend memory_search
* wxwindow_memorysearch_active();
306 template<typename T
> T
promptvalue(bool& bad
);
308 memory_search
* msearch
;
309 void on_mouse0(wxMouseEvent
& e
, bool polarity
);
311 void on_mouse2(wxMouseEvent
& e
);
312 void handle_undo_redo(bool redo
);
314 void handle_save(memory_search::savestate_type type
);
320 wxCheckBox
* hexmode2
;
321 wxCheckBox
* autoupdate
;
322 std::map
<uint64_t, uint64_t> addresses
;
324 uint64_t drag_startline
;
331 std::set
<std::string
> vmas_enabled
;
332 wxMenuItem
* undoitem
;
333 wxMenuItem
* redoitem
;
334 std::list
<std::vector
<char>> undohistory
;
335 std::list
<std::vector
<char>> redohistory
;
340 typedef void (wxwindow_memorysearch::*pokefn_t
)(uint64_t);
342 &wxwindow_memorysearch::_do_poke_addr
<int8_t>,
343 &wxwindow_memorysearch::_do_poke_addr
<uint8_t>,
344 &wxwindow_memorysearch::_do_poke_addr
<int16_t>,
345 &wxwindow_memorysearch::_do_poke_addr
<uint16_t>,
346 &wxwindow_memorysearch::_do_poke_addr
<ss_int24_t
>,
347 &wxwindow_memorysearch::_do_poke_addr
<ss_uint24_t
>,
348 &wxwindow_memorysearch::_do_poke_addr
<int32_t>,
349 &wxwindow_memorysearch::_do_poke_addr
<uint32_t>,
350 &wxwindow_memorysearch::_do_poke_addr
<int64_t>,
351 &wxwindow_memorysearch::_do_poke_addr
<uint64_t>,
352 &wxwindow_memorysearch::_do_poke_addr
<float>,
353 &wxwindow_memorysearch::_do_poke_addr
<double>,
356 typedef std::string (wxwindow_memorysearch::*displayfn_t
)(uint64_t, bool hexmode
, bool old
);
357 displayfn_t displays
[] = {
358 &wxwindow_memorysearch::_do_format_signed
<uint8_t>,
359 &wxwindow_memorysearch::_do_format_unsigned
<uint8_t>,
360 &wxwindow_memorysearch::_do_format_signed
<uint16_t>,
361 &wxwindow_memorysearch::_do_format_unsigned
<uint16_t>,
362 &wxwindow_memorysearch::_do_format_signed
<ss_uint24_t
>,
363 &wxwindow_memorysearch::_do_format_unsigned
<ss_uint24_t
>,
364 &wxwindow_memorysearch::_do_format_signed
<uint32_t>,
365 &wxwindow_memorysearch::_do_format_unsigned
<uint32_t>,
366 &wxwindow_memorysearch::_do_format_signed
<uint64_t>,
367 &wxwindow_memorysearch::_do_format_unsigned
<uint64_t>,
368 &wxwindow_memorysearch::_do_format_float
<float>,
369 &wxwindow_memorysearch::_do_format_float
<double>,
372 struct searchtype searchtbl
[] = {
375 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
376 &memory_search::s_value
<uint8_t>>,
377 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
378 &memory_search::s_value
<uint8_t>>,
379 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
380 &memory_search::s_value
<uint16_t>>,
381 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
382 &memory_search::s_value
<uint16_t>>,
383 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
384 &memory_search::s_value
<ss_uint24_t
>>,
385 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
386 &memory_search::s_value
<ss_uint24_t
>>,
387 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
388 &memory_search::s_value
<uint32_t>>,
389 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
390 &memory_search::s_value
<uint32_t>>,
391 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
392 &memory_search::s_value
<uint64_t>>,
393 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
394 &memory_search::s_value
<uint64_t>>,
395 &wxwindow_memorysearch::search_1
<float, float,
396 &memory_search::s_value
<float>>,
397 &wxwindow_memorysearch::search_1
<double, double,
398 &memory_search::s_value
<double>>
402 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
403 &memory_search::s_difference
<uint8_t>>,
404 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
405 &memory_search::s_difference
<uint8_t>>,
406 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
407 &memory_search::s_difference
<uint16_t>>,
408 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
409 &memory_search::s_difference
<uint16_t>>,
410 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
411 &memory_search::s_difference
<ss_uint24_t
>>,
412 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
413 &memory_search::s_difference
<ss_uint24_t
>>,
414 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
415 &memory_search::s_difference
<uint32_t>>,
416 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
417 &memory_search::s_difference
<uint32_t>>,
418 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
419 &memory_search::s_difference
<uint64_t>>,
420 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
421 &memory_search::s_difference
<uint64_t>>,
422 &wxwindow_memorysearch::search_1
<float, float,
423 &memory_search::s_difference
<float>>,
424 &wxwindow_memorysearch::search_1
<double, double,
425 &memory_search::s_difference
<double>>
429 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int8_t>>,
430 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint8_t>>,
431 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int16_t>>,
432 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint16_t>>,
433 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_int24_t
>>,
434 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_uint24_t
>>,
435 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int32_t>>,
436 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint32_t>>,
437 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int64_t>>,
438 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint64_t>>,
439 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
440 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
444 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int8_t>>,
445 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint8_t>>,
446 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int16_t>>,
447 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint16_t>>,
448 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_int24_t
>>,
449 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_uint24_t
>>,
450 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int32_t>>,
451 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint32_t>>,
452 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int64_t>>,
453 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint64_t>>,
454 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
455 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
459 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int8_t>>,
460 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint8_t>>,
461 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int16_t>>,
462 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint16_t>>,
463 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_int24_t
>>,
464 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_uint24_t
>>,
465 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int32_t>>,
466 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint32_t>>,
467 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int64_t>>,
468 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint64_t>>,
469 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<float>>,
470 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<double>>
474 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int8_t>>,
475 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint8_t>>,
476 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int16_t>>,
477 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint16_t>>,
478 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_int24_t
>>,
479 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_uint24_t
>>,
480 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int32_t>>,
481 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint32_t>>,
482 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int64_t>>,
483 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint64_t>>,
484 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<float>>,
485 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<double>>
489 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int8_t>>,
490 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint8_t>>,
491 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int16_t>>,
492 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint16_t>>,
493 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_int24_t
>>,
494 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_uint24_t
>>,
495 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int32_t>>,
496 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint32_t>>,
497 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int64_t>>,
498 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint64_t>>,
499 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
500 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
504 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int8_t>>,
505 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint8_t>>,
506 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int16_t>>,
507 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint16_t>>,
508 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_int24_t
>>,
509 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_uint24_t
>>,
510 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int32_t>>,
511 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint32_t>>,
512 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int64_t>>,
513 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint64_t>>,
514 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
515 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
519 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
520 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
521 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
522 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
523 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_int24_t
>>,
524 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_uint24_t
>>,
525 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
526 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
527 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
528 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
529 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
530 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
534 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
535 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
536 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
537 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
538 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_int24_t
>>,
539 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_uint24_t
>>,
540 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
541 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
542 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
543 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
544 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
545 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
549 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
550 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
551 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
552 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
553 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_int24_t
>>,
554 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_uint24_t
>>,
555 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
556 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
557 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
558 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
559 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
560 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
564 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
565 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
566 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
567 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
568 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_int24_t
>>,
569 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_uint24_t
>>,
570 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
571 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
572 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
573 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
574 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
575 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
579 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
580 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
581 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
582 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
583 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
584 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
585 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
586 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
587 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
588 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
589 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
590 &wxwindow_memorysearch::search_0
<&memory_search::update
>
596 wxwindow_memorysearch::wxwindow_memorysearch()
597 : wxFrame(NULL
, wxID_ANY
, wxT("lsnes: Memory Search"), wxDefaultPosition
, wxSize(-1, -1),
598 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
)
603 Connect(wxEVT_CLOSE_WINDOW
, wxCloseEventHandler(wxwindow_memorysearch::on_close
));
604 msearch
= new memory_search(lsnes_memory
);
606 wxFlexGridSizer
* toplevel
= new wxFlexGridSizer(4, 1, 0, 0);
609 wxBoxSizer
* buttons
= new wxBoxSizer(wxHORIZONTAL
);
610 buttons
->Add(tmp
= new wxButton(this, wxID_RESET
, wxT("Reset")), 0, wxGROW
);
611 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
613 buttons
->Add(new wxStaticText(this, wxID_ANY
, wxT("Data type:")), 0, wxGROW
);
614 wxString _datatypes
[DATATYPES
];
615 for(size_t i
= 0; i
< DATATYPES
; i
++)
616 _datatypes
[i
] = towxstring(datatypes
[i
]);
617 buttons
->Add(type
= new wxComboBox(this, wxID_TYPESELECT
, _datatypes
[typecode
], wxDefaultPosition
,
618 wxDefaultSize
, DATATYPES
, _datatypes
, wxCB_READONLY
), 0,
620 type
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
621 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
622 buttons
->Add(hexmode2
= new wxCheckBox(this, wxID_HEX_SELECT
, wxT("Hex display")), 0, wxGROW
);
623 buttons
->Add(autoupdate
= new wxCheckBox(this, wxID_AUTOUPDATE
, wxT("Update automatically")), 0, wxGROW
);
624 autoupdate
->SetValue(true);
625 hexmode2
->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED
,
626 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
627 toplevel
->Add(buttons
);
629 wxFlexGridSizer
* searches
= new wxFlexGridSizer(0, 6, 0, 0);
630 for(unsigned j
= 0; j
< sizeof(searchtbl
)/sizeof(searchtbl
[0]); j
++) {
631 std::string name
= searchtbl
[j
].name
;
632 searches
->Add(tmp
= new wxButton(this, wxID_BUTTONS_BASE
+ j
, towxstring(name
)), 1, wxGROW
);
633 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
634 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
636 toplevel
->Add(searches
);
638 toplevel
->Add(count
= new wxStaticText(this, wxID_ANY
, wxT("XXXXXX candidates")), 0, wxGROW
);
639 wxBoxSizer
* matchesb
= new wxBoxSizer(wxHORIZONTAL
);
640 matchesb
->Add(matches
= new panel(this), 1, wxGROW
);
641 matchesb
->Add(scroll
= new scroll_bar(this, wxID_ANY
, true), 0, wxGROW
);
642 toplevel
->Add(matchesb
, 1, wxGROW
);
644 scroll
->set_page_size(matches
->get_characters().second
);
646 for(auto i
: lsnes_memory
.get_regions())
647 if(memory_search::searchable_region(i
))
648 vmas_enabled
.insert(i
->name
);
650 wxMenuBar
* menubar
= new wxMenuBar();
652 wxMenu
* filemenu
= new wxMenu();
653 filemenu
->Append(wxID_MENU_DUMP_CANDIDATES
, wxT("Dump candidates..."));
654 filemenu
->AppendSeparator();
655 filemenu
->Append(wxID_MENU_SAVE_PREVMEM
, wxT("Save previous memory..."));
656 filemenu
->Append(wxID_MENU_SAVE_SET
, wxT("Save set of addresses..."));
657 filemenu
->Append(wxID_MENU_SAVE_ALL
, wxT("Save previous memory and set of addresses..."));
658 filemenu
->AppendSeparator();
659 filemenu
->Append(wxID_MENU_LOAD
, wxT("Load save..."));
660 menubar
->Append(filemenu
, wxT("File"));
661 wxMenu
* editmenu
= new wxMenu();
662 undoitem
= editmenu
->Append(wxID_UNDO
, wxT("Undo"));
663 redoitem
= editmenu
->Append(wxID_REDO
, wxT("Redo"));
664 undoitem
->Enable(false);
665 redoitem
->Enable(false);
666 menubar
->Append(editmenu
, wxT("Edit"));
667 Connect(wxID_MENU_DUMP_CANDIDATES
, wxEVT_COMMAND_MENU_SELECTED
,
668 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
669 Connect(wxID_MENU_SAVE_PREVMEM
, wxEVT_COMMAND_MENU_SELECTED
,
670 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
671 Connect(wxID_MENU_SAVE_SET
, wxEVT_COMMAND_MENU_SELECTED
,
672 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
673 Connect(wxID_MENU_SAVE_ALL
, wxEVT_COMMAND_MENU_SELECTED
,
674 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
675 Connect(wxID_MENU_LOAD
, wxEVT_COMMAND_MENU_SELECTED
,
676 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
677 Connect(wxID_UNDO
, wxEVT_COMMAND_MENU_SELECTED
,
678 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
679 Connect(wxID_REDO
, wxEVT_COMMAND_MENU_SELECTED
,
680 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
684 matches
->Connect(wxEVT_LEFT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
685 matches
->Connect(wxEVT_LEFT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
686 matches
->Connect(wxEVT_MIDDLE_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
687 matches
->Connect(wxEVT_MIDDLE_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
688 matches
->Connect(wxEVT_RIGHT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
689 matches
->Connect(wxEVT_RIGHT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
690 matches
->Connect(wxEVT_MOTION
, wxMouseEventHandler(wxwindow_memorysearch::on_mousedrag
), NULL
, this);
691 matches
->Connect(wxEVT_MOUSEWHEEL
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
692 scroll
->set_handler([this](scroll_bar
& s
) { this->matches
->request_paint(); });
694 toplevel
->SetSizeHints(this);
701 wxwindow_memorysearch::panel::panel(wxwindow_memorysearch
* _parent
)
702 : text_framebuffer_panel(_parent
, 40, 25, wxID_ANY
, NULL
)
709 void wxwindow_memorysearch::panel::prepare_paint()
711 uint64_t first
= parent
->scroll
->get_position();
712 auto ssize
= get_characters();
713 uint64_t last
= first
+ ssize
.second
;
714 std::vector
<std::string
> lines
;
715 lines
.reserve(ssize
.second
);
716 std::map
<uint64_t, uint64_t> addrs
;
717 auto* ms
= parent
->msearch
;
719 bool toomany
= false;
720 auto _parent
= parent
;
721 runemufn([&toomany
, &first
, &last
, ms
, &lines
, &addrs
, &addr_count
, _parent
]() {
722 addr_count
= ms
->get_candidate_count();
723 if(last
> addr_count
) {
724 uint64_t delta
= last
- addr_count
;
733 if(addr_count
<= CANDIDATE_LIMIT
) {
734 std::list
<uint64_t> addrs2
= ms
->get_candidates();
736 for(auto i
: addrs2
) {
737 std::string row
= hex::to(i
) + " ";
738 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, false);
740 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, true);
742 if(j
>= first
&& j
< last
)
743 lines
.push_back(row
);
747 lines
.push_back("Too many candidates to display");
751 std::swap(parent
->addresses
, addrs
);
753 std::ostringstream x
;
754 x
<< addr_count
<< " " << ((addr_count
!= 1) ? "candidates" : "candidate");
755 parent
->count
->SetLabel(towxstring(x
.str()));
758 for(unsigned i
= 0; i
< lines
.size(); i
++) {
759 bool sel
= (first
+ i
) >= first_sel
&& (first
+ i
) < last_sel
;
760 write(lines
[i
], 0, 0, i
, sel
? 0xFFFFFF : 0, sel
? 0 : 0xFFFFFF);
768 parent
->toomany
= toomany
;
769 parent
->scroll
->set_range(toomany
? 0 : addr_count
);
772 void wxwindow_memorysearch::panel::set_selection(uint64_t first
, uint64_t last
)
779 void wxwindow_memorysearch::panel::get_selection(uint64_t& first
, uint64_t& last
)
785 wxwindow_memorysearch::~wxwindow_memorysearch()
791 bool wxwindow_memorysearch::ShouldPreventAppExit() const
796 void wxwindow_memorysearch::dump_candidates_text()
799 std::string filename
= choose_file_save(this, "Dump memory search", project_otherpath(),
801 std::ofstream
out(filename
);
803 runemufn([ms
, this, &out
]() {
804 std::list
<uint64_t> addrs2
= ms
->get_candidates();
805 for(auto i
: addrs2
) {
806 std::string row
= hex::to(i
) + " ";
807 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, false);
809 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, true);
811 out
<< row
<< std::endl
;
815 throw std::runtime_error("Can't write save file");
816 } catch(canceled_exception
& e
) {
817 } catch(std::exception
& e
) {
818 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
823 void wxwindow_memorysearch::handle_save(memory_search::savestate_type type
)
826 std::vector
<char> state
;
827 msearch
->savestate(state
, type
);
828 std::string filename
= choose_file_save(this, "Save memory search", project_otherpath(),
829 filetype_memorysearch
);
830 std::ofstream
out(filename
, std::ios::binary
);
831 out
.write(&state
[0], state
.size());
833 throw std::runtime_error("Can't write save file");
834 } catch(canceled_exception
& e
) {
835 } catch(std::exception
& e
) {
836 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
841 void wxwindow_memorysearch::handle_load()
844 std::string filename
= choose_file_load(this, "Load memory search", project_otherpath(),
845 filetype_memorysearch
);
846 std::vector
<char> state
= zip::readrel(filename
, "");
848 msearch
->loadstate(state
);
850 } catch(canceled_exception
& e
) {
851 } catch(std::exception
& e
) {
852 show_message_ok(this, "Load error", std::string(e
.what()), wxICON_WARNING
);
857 void wxwindow_memorysearch::handle_undo_redo(bool redo
)
859 std::list
<std::vector
<char>>& a
= *(redo
? &redohistory
: &undohistory
);
860 std::list
<std::vector
<char>>& b
= *(redo
? &undohistory
: &redohistory
);
862 show_message_ok(this, "Undo/Redo error", "Can't find state to undo/redo to", wxICON_WARNING
);
867 std::vector
<char> state
;
868 msearch
->savestate(state
, memory_search::ST_SET
);
871 msearch
->loadstate(a
.back());
873 } catch(std::exception
& e
) {
876 show_message_ok(this, "Undo/Redo error", std::string(e
.what()), wxICON_WARNING
);
879 undoitem
->Enable(undohistory
.size());
880 redoitem
->Enable(redohistory
.size());
884 void wxwindow_memorysearch::push_undo()
887 std::vector
<char> state
;
888 msearch
->savestate(state
, memory_search::ST_SET
);
889 undohistory
.push_back(state
);
890 if(undohistory
.size() > UNDOHISTORY_MAXSIZE
)
891 undohistory
.pop_front();
893 undoitem
->Enable(undohistory
.size());
894 redoitem
->Enable(redohistory
.size());
899 void wxwindow_memorysearch::on_mouse(wxMouseEvent
& e
)
901 if(e
.RightUp() || (e
.LeftUp() && e
.ControlDown()))
903 else if(e
.LeftDown())
910 if(e
.ShiftDown() && e
.ControlDown())
912 scroll
->apply_wheel(e
.GetWheelRotation(), e
.GetWheelDelta(), speed
);
915 void wxwindow_memorysearch::on_mouse0(wxMouseEvent
& e
, bool polarity
)
917 dragging
= polarity
&& !toomany
;
921 uint64_t first
= scroll
->get_position();
922 drag_startline
= first
+ e
.GetY() / matches
->get_cell().second
;
923 } else if(mpx
== e
.GetX() && mpy
== e
.GetY()) {
924 matches
->set_selection(0, 0);
928 void wxwindow_memorysearch::on_mousedrag(wxMouseEvent
& e
)
932 uint64_t first
= scroll
->get_position();
933 uint64_t linenow
= first
+ e
.GetY() / matches
->get_cell().second
;
934 if(drag_startline
< linenow
)
935 matches
->set_selection(drag_startline
, linenow
+ 1);
937 matches
->set_selection(linenow
, drag_startline
+ 1);
940 void wxwindow_memorysearch::on_mouse2(wxMouseEvent
& e
)
944 uint64_t selcount
= 0;
946 matches
->get_selection(start
, end
);
947 some_selected
= (start
< end
);
949 uint64_t first
= scroll
->get_position();
950 act_line
= first
+ e
.GetY() / matches
->get_cell().second
;
951 if(addresses
.count(act_line
)) {
952 some_selected
= true;
956 menu
.Append(wxID_ADD
, wxT("Add watch..."))->Enable(some_selected
);
957 menu
.Append(wxID_SHOW_HEXEDITOR
, wxT("Select in hex editor"))->Enable(selcount
== 1 &&
958 wxeditor_hexeditor_available());
959 menu
.Append(wxID_POKE
, wxT("Poke..."))->Enable(selcount
== 1);
960 menu
.AppendSeparator();
961 menu
.Append(wxID_DISQUALIFY
, wxT("Disqualify"))->Enable(some_selected
);
962 menu
.AppendSeparator();
963 menu
.Append(wxID_UPDATE
, wxT("Update"));
964 menu
.Append(wxID_SET_REGIONS
, wxT("Enabled VMAs"));
965 menu
.Connect(wxEVT_COMMAND_MENU_SELECTED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
970 void wxwindow_memorysearch::on_close(wxCloseEvent
& e
)
976 void wxwindow_memorysearch::auto_update()
978 if(autoupdate
->GetValue())
982 void wxwindow_memorysearch::update()
984 matches
->request_paint();
987 void wxwindow_memorysearch::on_button_click(wxCommandEvent
& e
)
990 if(id
== wxID_RESET
) {
993 for(auto i
: lsnes_memory
.get_regions())
994 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
995 msearch
->dq_range(i
->base
, i
->last_address());
996 wxeditor_hexeditor_update();
997 } else if(id
== wxID_UPDATE
) {
999 } else if(id
== wxID_TYPESELECT
) {
1000 wxString c
= type
->GetValue();
1001 for(unsigned i
= 0; i
< DATATYPES
; i
++)
1002 if(c
== towxstring(datatypes
[i
]))
1004 } else if(id
== wxID_HEX_SELECT
) {
1005 hexmode
= hexmode2
->GetValue();
1006 } else if(id
== wxID_ADD
) {
1007 uint64_t start
, end
;
1008 matches
->get_selection(start
, end
);
1013 for(uint64_t r
= start
; r
< end
; r
++) {
1014 if(!addresses
.count(r
))
1016 uint64_t addr
= addresses
[r
];
1018 std::string n
= pick_text(this, "Name for watch", (stringfmt()
1019 << "Enter name for watch at 0x" << std::hex
<< addr
<< ":").str());
1022 lsnes_memorywatch_item e
;
1023 e
.expr
= (stringfmt() << addr
).str();
1024 bool is_hex
= hexmode2
->GetValue();
1025 e
.bytes
= watch_properties
[typecode
].len
;
1026 e
.signed_flag
= !is_hex
&& (watch_properties
[typecode
].type
== 1);
1027 e
.float_flag
= (watch_properties
[typecode
].type
== 2);
1028 if(e
.float_flag
) is_hex
= false;
1029 e
.format
= is_hex
? watch_properties
[typecode
].hformat
: "";
1030 auto i
= lsnes_memory
.get_regions();
1033 if(addr
>= j
->base
&& addr
< j
->base
+ j
->size
)
1034 endianess
= j
->endian
;
1036 e
.endianess
= endianess
;
1037 runemufn([n
, &e
]() { lsnes_memorywatch
.set(n
, e
); });
1038 } catch(canceled_exception
& e
) {
1041 matches
->set_selection(0, 0);
1042 } else if(id
== wxID_DISQUALIFY
) {
1043 uint64_t start
, end
;
1044 matches
->get_selection(start
, end
);
1050 for(uint64_t r
= start
; r
< end
; r
++) {
1051 if(!addresses
.count(r
))
1053 uint64_t addr
= addresses
[r
];
1055 runemufn([addr
, ms
]() { ms
->dq_range(addr
, addr
); });
1057 matches
->set_selection(0, 0);
1058 wxeditor_hexeditor_update();
1059 } else if(id
== wxID_SET_REGIONS
) {
1060 wxwindow_memorysearch_vmasel
* d
= new wxwindow_memorysearch_vmasel(this, vmas_enabled
);
1061 if(d
->ShowModal() == wxID_OK
)
1062 vmas_enabled
= d
->get_vmas();
1069 for(auto i
: lsnes_memory
.get_regions())
1070 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
1071 msearch
->dq_range(i
->base
, i
->last_address());
1072 wxeditor_hexeditor_update();
1073 } else if(id
== wxID_POKE
) {
1074 uint64_t start
, end
;
1075 matches
->get_selection(start
, end
);
1080 for(uint64_t r
= start
; r
< end
; r
++) {
1081 if(!addresses
.count(r
))
1083 uint64_t addr
= addresses
[r
];
1085 (this->*(pokes
[typecode
]))(addr
);
1086 } catch(canceled_exception
& e
) {
1090 } else if(id
== wxID_SHOW_HEXEDITOR
) {
1091 uint64_t start
, end
;
1092 matches
->get_selection(start
, end
);
1097 for(uint64_t r
= start
; r
< end
; r
++) {
1098 if(!addresses
.count(r
))
1100 wxeditor_hexeditor_jumpto(addresses
[r
]);
1103 } else if(id
>= wxID_BUTTONS_BASE
&& id
< wxID_BUTTONS_BASE
+
1104 (ssize_t
)(sizeof(searchtbl
)/sizeof(searchtbl
[0]))) {
1105 int button
= id
- wxID_BUTTONS_BASE
;
1107 uint64_t old_count
= msearch
->get_candidate_count();
1108 (this->*(searchtbl
[button
].searches
[typecode
]))();
1109 uint64_t new_count
= msearch
->get_candidate_count();
1110 if(old_count
== new_count
) {
1111 undohistory
.pop_back(); //Shouldn't be undoable.
1112 undoitem
->Enable(undohistory
.size());
1114 wxeditor_hexeditor_update();
1115 } else if(id
== wxID_MENU_DUMP_CANDIDATES
) {
1116 dump_candidates_text();
1117 } else if(id
== wxID_MENU_SAVE_PREVMEM
) {
1118 handle_save(memory_search::ST_PREVMEM
);
1119 } else if(id
== wxID_MENU_SAVE_SET
) {
1120 handle_save(memory_search::ST_SET
);
1121 } else if(id
== wxID_MENU_SAVE_ALL
) {
1122 handle_save(memory_search::ST_ALL
);
1123 } else if(id
== wxID_MENU_LOAD
) {
1125 } else if(id
== wxID_UNDO
) {
1126 handle_undo_redo(false);
1127 } else if(id
== wxID_REDO
) {
1128 handle_undo_redo(true);
1133 template<typename T
> void wxwindow_memorysearch::_do_poke_addr(uint64_t addr
)
1135 T val
= msearch
->v_read
<T
>(addr
);
1138 v
= pick_text(this, "Poke value", (stringfmt() << "Enter value to poke to " << std::hex
<< "0x"
1139 << addr
).str(), (stringfmt() << val
).str(), false);
1140 val
= parse_value
<T
>(v
);
1141 } catch(canceled_exception
& e
) {
1144 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1147 msearch
->v_write
<T
>(addr
, val
);
1150 template<void(memory_search::*sfn
)()> void wxwindow_memorysearch::search_0()
1155 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void wxwindow_memorysearch::search_1()
1158 T val
= promptvalue
<T
>(bad
);
1161 (msearch
->*sfn
)(static_cast<T2
>(val
));
1164 template<typename T
> T
wxwindow_memorysearch::promptvalue(bool& bad
)
1167 wxTextEntryDialog
* d
= new wxTextEntryDialog(this, wxT("Enter value to search for:"), wxT("Memory search"),
1169 if(d
->ShowModal() == wxID_CANCEL
) {
1173 v
= tostdstring(d
->GetValue());
1177 val2
= parse_value
<T
>(v
);
1179 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1186 void wxwindow_memorysearch_display()
1192 mwatch
= new wxwindow_memorysearch();
1196 void wxwindow_memorysearch_update()
1199 mwatch
->auto_update();
1202 memory_search
* wxwindow_memorysearch_active()
1205 return mwatch
->msearch
;