1 #include "core/dispatch.hpp"
2 #include "core/memorymanip.hpp"
3 #include "core/memorywatch.hpp"
4 #include "core/project.hpp"
5 #include "library/string.hpp"
6 #include "library/memorysearch.hpp"
7 #include "library/int24.hpp"
8 #include "library/zip.hpp"
10 #include "platform/wxwidgets/loadsave.hpp"
11 #include "platform/wxwidgets/platform.hpp"
12 #include "platform/wxwidgets/scrollbar.hpp"
13 #include "platform/wxwidgets/textrender.hpp"
21 #include <wx/control.h>
22 #include <wx/combobox.h>
24 #define wxID_RESET (wxID_HIGHEST + 1)
25 #define wxID_UPDATE (wxID_HIGHEST + 2)
26 #define wxID_TYPESELECT (wxID_HIGHEST + 3)
27 #define wxID_HEX_SELECT (wxID_HIGHEST + 4)
28 #define wxID_ADD (wxID_HIGHEST + 5)
29 #define wxID_SET_REGIONS (wxID_HIGHEST + 6)
30 #define wxID_AUTOUPDATE (wxID_HIGHEST + 7)
31 #define wxID_DISQUALIFY (wxID_HIGHEST + 8)
32 #define wxID_POKE (wxID_HIGHEST + 9)
33 #define wxID_SHOW_HEXEDITOR (wxID_HIGHEST + 10)
34 #define wxID_MENU_SAVE_PREVMEM (wxID_HIGHEST + 11)
35 #define wxID_MENU_SAVE_SET (wxID_HIGHEST + 12)
36 #define wxID_MENU_SAVE_ALL (wxID_HIGHEST + 13)
37 #define wxID_MENU_LOAD (wxID_HIGHEST + 14)
38 #define wxID_MENU_UNDO (wxID_HIGHEST + 15)
39 #define wxID_MENU_REDO (wxID_HIGHEST + 16)
40 #define wxID_MENU_DUMP_CANDIDATES (wxID_HIGHEST + 17)
41 #define wxID_BUTTONS_BASE (wxID_HIGHEST + 128)
44 #define CANDIDATE_LIMIT 512
46 class wxwindow_memorysearch
;
47 memory_search
* wxwindow_memorysearch_active();
51 unsigned UNDOHISTORY_MAXSIZE
= 48;
52 const char* watchchars
= "bBwWoOdDqQfF";
54 wxwindow_memorysearch
* mwatch
;
56 const char* datatypes
[] = {
71 typedef void (wxwindow_memorysearch::*search_fn_t
)();
76 search_fn_t searches
[DATATYPES
];
79 std::string
hexformat_address(uint64_t addr
)
82 x
<< std::setfill('0') << std::setw(16) << std::hex
<< addr
;
86 template<typename T
> std::string
format_number_signed(T val
, bool hex
);
87 template<typename T
> std::string
format_number_unsigned(T val
, bool hex
);
89 template<typename T
> std::string
format_number_signedh(T val
, unsigned hwidth
, bool hex
)
94 x
<< "+" << std::setfill('0') << std::setw(hwidth
) << std::hex
<<
95 static_cast<uint64_t>(val
);
98 uint64_t y
= static_cast<uint64_t>(y2
);
99 x
<< "-" << std::setfill('0') << std::setw(hwidth
) << std::hex
<< (~y
+ 1);
102 x
<< static_cast<int64_t>(val
);
106 template<typename T
> std::string
format_number_unsignedh(T val
, unsigned hwidth
, bool hex
)
108 std::ostringstream x
;
110 x
<< std::setfill('0') << std::setw(hwidth
) << std::hex
<< static_cast<uint64_t>(val
);
112 x
<< static_cast<uint64_t>(val
);
116 template<> std::string format_number_signed
<uint8_t>(uint8_t val
, bool hex
)
118 return format_number_signedh(static_cast<int8_t>(val
), 2, hex
);
121 template<> std::string format_number_signed
<uint16_t>(uint16_t val
, bool hex
)
123 return format_number_signedh(static_cast<int16_t>(val
), 4, hex
);
126 template<> std::string format_number_signed
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
128 return format_number_signedh((int32_t)(uint32_t)(val
), 6, hex
);
131 template<> std::string format_number_signed
<uint32_t>(uint32_t val
, bool hex
)
133 return format_number_signedh(static_cast<int32_t>(val
), 8, hex
);
136 template<> std::string format_number_signed
<uint64_t>(uint64_t val
, bool hex
)
138 return format_number_signedh(static_cast<int64_t>(val
), 16, hex
);
141 template<> std::string format_number_unsigned
<uint8_t>(uint8_t val
, bool hex
)
143 return format_number_unsignedh(val
, 2, hex
);
146 template<> std::string format_number_unsigned
<uint16_t>(uint16_t val
, bool hex
)
148 return format_number_unsignedh(val
, 4, hex
);
151 template<> std::string format_number_unsigned
<ss_uint24_t
>(ss_uint24_t val
, bool hex
)
153 return format_number_unsignedh(val
, 6, hex
);
156 template<> std::string format_number_unsigned
<uint32_t>(uint32_t val
, bool hex
)
158 return format_number_unsignedh(val
, 8, hex
);
161 template<> std::string format_number_unsigned
<uint64_t>(uint64_t val
, bool hex
)
163 return format_number_unsignedh(val
, 16, hex
);
166 std::string
format_number_float(double val
)
168 return (stringfmt() << val
).str();
172 class wxwindow_memorysearch_vmasel
: public wxDialog
175 wxwindow_memorysearch_vmasel(wxWindow
* p
, const std::set
<std::string
>& enabled
);
176 bool ShouldPreventAppExit() const;
177 std::set
<std::string
> get_vmas();
178 void on_ok(wxCommandEvent
& e
);
179 void on_cancel(wxCommandEvent
& e
);
181 std::set
<std::string
> vmas
;
182 std::vector
<wxCheckBox
*> checkboxes
;
187 wxwindow_memorysearch_vmasel::wxwindow_memorysearch_vmasel(wxWindow
* p
, const std::set
<std::string
>& enabled
)
188 : wxDialog(p
, wxID_ANY
, towxstring("lsnes: Select enabled regions"), wxDefaultPosition
, wxSize(300, -1))
190 auto i
= lsnes_memory
.get_regions();
192 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(i
.size() + 1, 1, 0, 0);
195 if(j
->readonly
|| j
->special
)
198 top_s
->Add(t
= new wxCheckBox(this, wxID_ANY
, towxstring(j
->name
)), 0, wxGROW
);
199 if(enabled
.count(j
->name
))
201 checkboxes
.push_back(t
);
203 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
204 pbutton_s
->AddStretchSpacer();
205 pbutton_s
->Add(ok
= new wxButton(this, wxID_ANY
, wxT("Ok")), 0, wxGROW
);
206 pbutton_s
->Add(cancel
= new wxButton(this, wxID_ANY
, wxT("Cancel")), 0, wxGROW
);
207 ok
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
208 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_ok
), NULL
, this);
209 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
210 wxCommandEventHandler(wxwindow_memorysearch_vmasel::on_cancel
), NULL
, this);
211 top_s
->Add(pbutton_s
);
213 pbutton_s
->SetSizeHints(this);
214 top_s
->SetSizeHints(this);
218 bool wxwindow_memorysearch_vmasel::ShouldPreventAppExit() const
223 std::set
<std::string
> wxwindow_memorysearch_vmasel::get_vmas()
228 void wxwindow_memorysearch_vmasel::on_ok(wxCommandEvent
& e
)
230 for(auto i
: checkboxes
)
232 vmas
.insert(tostdstring(i
->GetLabel()));
236 void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent
& e
)
238 EndModal(wxID_CANCEL
);
242 class wxwindow_memorysearch
: public wxFrame
245 class panel
: public text_framebuffer_panel
248 panel(wxwindow_memorysearch
* parent
);
249 void set_selection(uint64_t first
, uint64_t last
);
250 void get_selection(uint64_t& first
, uint64_t& last
);
252 void prepare_paint();
254 wxwindow_memorysearch
* parent
;
258 wxwindow_memorysearch();
259 ~wxwindow_memorysearch();
260 bool ShouldPreventAppExit() const;
261 void on_close(wxCloseEvent
& e
);
262 void on_button_click(wxCommandEvent
& e
);
264 void on_mousedrag(wxMouseEvent
& e
);
265 void on_mouse(wxMouseEvent
& e
);
267 template<void(memory_search::*sfn
)()> void search_0();
268 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void search_1();
269 template<typename T
> void _do_poke_addr(uint64_t addr
);
270 template<typename T
> std::string
_do_format_signed(uint64_t addr
, bool hex
, bool old
)
273 return format_number_signed
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
275 return format_number_signed
<T
>(lsnes_memory
.read
<T
>(addr
), hex
);
277 template<typename T
> std::string
_do_format_unsigned(uint64_t addr
, bool hex
, bool old
)
280 return format_number_unsigned
<T
>(msearch
->v_readold
<T
>(addr
), hex
);
282 return format_number_unsigned
<T
>(lsnes_memory
.read
<T
>(addr
), hex
);
284 template<typename T
> std::string
_do_format_float(uint64_t addr
, bool hex
, bool old
)
287 return format_number_float(msearch
->v_readold
<T
>(addr
));
289 return format_number_float(lsnes_memory
.read
<T
>(addr
));
291 void dump_candidates_text();
293 friend memory_search
* wxwindow_memorysearch_active();
295 template<typename T
> T
promptvalue(bool& bad
);
297 memory_search
* msearch
;
298 void on_mouse0(wxMouseEvent
& e
, bool polarity
);
300 void on_mouse2(wxMouseEvent
& e
);
301 void handle_undo_redo(bool redo
);
303 void handle_save(memory_search::savestate_type type
);
309 wxCheckBox
* hexmode2
;
310 wxCheckBox
* autoupdate
;
311 std::map
<uint64_t, uint64_t> addresses
;
313 uint64_t drag_startline
;
320 std::set
<std::string
> vmas_enabled
;
321 wxMenuItem
* undoitem
;
322 wxMenuItem
* redoitem
;
323 std::list
<std::vector
<char>> undohistory
;
324 std::list
<std::vector
<char>> redohistory
;
329 typedef void (wxwindow_memorysearch::*pokefn_t
)(uint64_t);
331 &wxwindow_memorysearch::_do_poke_addr
<int8_t>,
332 &wxwindow_memorysearch::_do_poke_addr
<uint8_t>,
333 &wxwindow_memorysearch::_do_poke_addr
<int16_t>,
334 &wxwindow_memorysearch::_do_poke_addr
<uint16_t>,
335 &wxwindow_memorysearch::_do_poke_addr
<ss_int24_t
>,
336 &wxwindow_memorysearch::_do_poke_addr
<ss_uint24_t
>,
337 &wxwindow_memorysearch::_do_poke_addr
<int32_t>,
338 &wxwindow_memorysearch::_do_poke_addr
<uint32_t>,
339 &wxwindow_memorysearch::_do_poke_addr
<int64_t>,
340 &wxwindow_memorysearch::_do_poke_addr
<uint64_t>,
341 &wxwindow_memorysearch::_do_poke_addr
<float>,
342 &wxwindow_memorysearch::_do_poke_addr
<double>,
345 typedef std::string (wxwindow_memorysearch::*displayfn_t
)(uint64_t, bool hexmode
, bool old
);
346 displayfn_t displays
[] = {
347 &wxwindow_memorysearch::_do_format_signed
<uint8_t>,
348 &wxwindow_memorysearch::_do_format_unsigned
<uint8_t>,
349 &wxwindow_memorysearch::_do_format_signed
<uint16_t>,
350 &wxwindow_memorysearch::_do_format_unsigned
<uint16_t>,
351 &wxwindow_memorysearch::_do_format_signed
<ss_uint24_t
>,
352 &wxwindow_memorysearch::_do_format_unsigned
<ss_uint24_t
>,
353 &wxwindow_memorysearch::_do_format_signed
<uint32_t>,
354 &wxwindow_memorysearch::_do_format_signed
<uint32_t>,
355 &wxwindow_memorysearch::_do_format_unsigned
<uint64_t>,
356 &wxwindow_memorysearch::_do_format_unsigned
<uint64_t>,
357 &wxwindow_memorysearch::_do_format_float
<float>,
358 &wxwindow_memorysearch::_do_format_float
<double>,
361 struct searchtype searchtbl
[] = {
364 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
365 &memory_search::s_value
<uint8_t>>,
366 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
367 &memory_search::s_value
<uint8_t>>,
368 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
369 &memory_search::s_value
<uint16_t>>,
370 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
371 &memory_search::s_value
<uint16_t>>,
372 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
373 &memory_search::s_value
<ss_uint24_t
>>,
374 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
375 &memory_search::s_value
<ss_uint24_t
>>,
376 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
377 &memory_search::s_value
<uint32_t>>,
378 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
379 &memory_search::s_value
<uint32_t>>,
380 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
381 &memory_search::s_value
<uint64_t>>,
382 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
383 &memory_search::s_value
<uint64_t>>,
384 &wxwindow_memorysearch::search_1
<float, float,
385 &memory_search::s_value
<float>>,
386 &wxwindow_memorysearch::search_1
<double, double,
387 &memory_search::s_value
<double>>
391 &wxwindow_memorysearch::search_1
<int8_t, uint8_t,
392 &memory_search::s_difference
<uint8_t>>,
393 &wxwindow_memorysearch::search_1
<uint8_t, uint8_t,
394 &memory_search::s_difference
<uint8_t>>,
395 &wxwindow_memorysearch::search_1
<int16_t, uint16_t,
396 &memory_search::s_difference
<uint16_t>>,
397 &wxwindow_memorysearch::search_1
<uint16_t, uint16_t,
398 &memory_search::s_difference
<uint16_t>>,
399 &wxwindow_memorysearch::search_1
<ss_int24_t
, ss_uint24_t
,
400 &memory_search::s_difference
<ss_uint24_t
>>,
401 &wxwindow_memorysearch::search_1
<ss_uint24_t
, ss_uint24_t
,
402 &memory_search::s_difference
<ss_uint24_t
>>,
403 &wxwindow_memorysearch::search_1
<int32_t, uint32_t,
404 &memory_search::s_difference
<uint32_t>>,
405 &wxwindow_memorysearch::search_1
<uint32_t, uint32_t,
406 &memory_search::s_difference
<uint32_t>>,
407 &wxwindow_memorysearch::search_1
<int64_t, uint64_t,
408 &memory_search::s_difference
<uint64_t>>,
409 &wxwindow_memorysearch::search_1
<uint64_t, uint64_t,
410 &memory_search::s_difference
<uint64_t>>,
411 &wxwindow_memorysearch::search_1
<float, float,
412 &memory_search::s_difference
<float>>,
413 &wxwindow_memorysearch::search_1
<double, double,
414 &memory_search::s_difference
<double>>
418 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int8_t>>,
419 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint8_t>>,
420 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int16_t>>,
421 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint16_t>>,
422 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_int24_t
>>,
423 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<ss_uint24_t
>>,
424 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int32_t>>,
425 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint32_t>>,
426 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<int64_t>>,
427 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<uint64_t>>,
428 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
429 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
433 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int8_t>>,
434 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint8_t>>,
435 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int16_t>>,
436 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint16_t>>,
437 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_int24_t
>>,
438 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<ss_uint24_t
>>,
439 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int32_t>>,
440 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint32_t>>,
441 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<int64_t>>,
442 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<uint64_t>>,
443 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
444 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
448 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int8_t>>,
449 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint8_t>>,
450 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int16_t>>,
451 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint16_t>>,
452 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_int24_t
>>,
453 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<ss_uint24_t
>>,
454 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int32_t>>,
455 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint32_t>>,
456 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<int64_t>>,
457 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<uint64_t>>,
458 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<float>>,
459 &wxwindow_memorysearch::search_0
<&memory_search::s_eq
<double>>
463 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int8_t>>,
464 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint8_t>>,
465 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int16_t>>,
466 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint16_t>>,
467 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_int24_t
>>,
468 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<ss_uint24_t
>>,
469 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int32_t>>,
470 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint32_t>>,
471 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<int64_t>>,
472 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<uint64_t>>,
473 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<float>>,
474 &wxwindow_memorysearch::search_0
<&memory_search::s_ne
<double>>
478 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int8_t>>,
479 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint8_t>>,
480 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int16_t>>,
481 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint16_t>>,
482 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_int24_t
>>,
483 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<ss_uint24_t
>>,
484 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int32_t>>,
485 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint32_t>>,
486 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<int64_t>>,
487 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<uint64_t>>,
488 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
489 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
493 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int8_t>>,
494 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint8_t>>,
495 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int16_t>>,
496 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint16_t>>,
497 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_int24_t
>>,
498 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<ss_uint24_t
>>,
499 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int32_t>>,
500 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint32_t>>,
501 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<int64_t>>,
502 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<uint64_t>>,
503 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
504 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
508 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
509 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint8_t>>,
510 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
511 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint16_t>>,
512 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_int24_t
>>,
513 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<ss_uint24_t
>>,
514 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
515 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint32_t>>,
516 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
517 &wxwindow_memorysearch::search_0
<&memory_search::s_seqlt
<uint64_t>>,
518 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<float>>,
519 &wxwindow_memorysearch::search_0
<&memory_search::s_lt
<double>>
523 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
524 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint8_t>>,
525 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
526 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint16_t>>,
527 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_int24_t
>>,
528 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<ss_uint24_t
>>,
529 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
530 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint32_t>>,
531 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
532 &wxwindow_memorysearch::search_0
<&memory_search::s_seqle
<uint64_t>>,
533 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<float>>,
534 &wxwindow_memorysearch::search_0
<&memory_search::s_le
<double>>
538 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
539 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint8_t>>,
540 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
541 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint16_t>>,
542 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_int24_t
>>,
543 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<ss_uint24_t
>>,
544 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
545 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint32_t>>,
546 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
547 &wxwindow_memorysearch::search_0
<&memory_search::s_seqge
<uint64_t>>,
548 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<float>>,
549 &wxwindow_memorysearch::search_0
<&memory_search::s_ge
<double>>
553 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
554 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint8_t>>,
555 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
556 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint16_t>>,
557 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_int24_t
>>,
558 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<ss_uint24_t
>>,
559 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
560 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint32_t>>,
561 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
562 &wxwindow_memorysearch::search_0
<&memory_search::s_seqgt
<uint64_t>>,
563 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<float>>,
564 &wxwindow_memorysearch::search_0
<&memory_search::s_gt
<double>>
568 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
569 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
570 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
571 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
572 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
573 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
574 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
575 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
576 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
577 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
578 &wxwindow_memorysearch::search_0
<&memory_search::update
>,
579 &wxwindow_memorysearch::search_0
<&memory_search::update
>
585 wxwindow_memorysearch::wxwindow_memorysearch()
586 : wxFrame(NULL
, wxID_ANY
, wxT("lsnes: Memory Search"), wxDefaultPosition
, wxSize(-1, -1),
587 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
)
592 Connect(wxEVT_CLOSE_WINDOW
, wxCloseEventHandler(wxwindow_memorysearch::on_close
));
593 msearch
= new memory_search(lsnes_memory
);
595 wxFlexGridSizer
* toplevel
= new wxFlexGridSizer(4, 1, 0, 0);
598 wxBoxSizer
* buttons
= new wxBoxSizer(wxHORIZONTAL
);
599 buttons
->Add(tmp
= new wxButton(this, wxID_RESET
, wxT("Reset")), 0, wxGROW
);
600 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
602 buttons
->Add(new wxStaticText(this, wxID_ANY
, wxT("Data type:")), 0, wxGROW
);
603 wxString _datatypes
[DATATYPES
];
604 for(size_t i
= 0; i
< DATATYPES
; i
++)
605 _datatypes
[i
] = towxstring(datatypes
[i
]);
606 buttons
->Add(type
= new wxComboBox(this, wxID_TYPESELECT
, _datatypes
[typecode
], wxDefaultPosition
,
607 wxDefaultSize
, DATATYPES
, _datatypes
, wxCB_READONLY
), 0,
609 type
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
610 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
611 buttons
->Add(hexmode2
= new wxCheckBox(this, wxID_HEX_SELECT
, wxT("Hex display")), 0, wxGROW
);
612 buttons
->Add(autoupdate
= new wxCheckBox(this, wxID_AUTOUPDATE
, wxT("Update automatically")), 0, wxGROW
);
613 autoupdate
->SetValue(true);
614 hexmode2
->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED
,
615 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
616 toplevel
->Add(buttons
);
618 wxFlexGridSizer
* searches
= new wxFlexGridSizer(0, 6, 0, 0);
619 for(unsigned j
= 0; j
< sizeof(searchtbl
)/sizeof(searchtbl
[0]); j
++) {
620 std::string name
= searchtbl
[j
].name
;
621 searches
->Add(tmp
= new wxButton(this, wxID_BUTTONS_BASE
+ j
, towxstring(name
)), 1, wxGROW
);
622 tmp
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
623 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
), NULL
, this);
625 toplevel
->Add(searches
);
627 toplevel
->Add(count
= new wxStaticText(this, wxID_ANY
, wxT("XXXXXX candidates")), 0, wxGROW
);
628 wxBoxSizer
* matchesb
= new wxBoxSizer(wxHORIZONTAL
);
629 matchesb
->Add(matches
= new panel(this), 1, wxGROW
);
630 matchesb
->Add(scroll
= new scroll_bar(this, wxID_ANY
, true), 0, wxGROW
);
631 toplevel
->Add(matchesb
, 1, wxGROW
);
633 scroll
->set_page_size(matches
->get_characters().second
);
635 for(auto i
: lsnes_memory
.get_regions())
636 if(memory_search::searchable_region(i
))
637 vmas_enabled
.insert(i
->name
);
639 wxMenuBar
* menubar
= new wxMenuBar();
641 wxMenu
* filemenu
= new wxMenu();
642 filemenu
->Append(wxID_MENU_DUMP_CANDIDATES
, wxT("Dump candidates..."));
643 filemenu
->AppendSeparator();
644 filemenu
->Append(wxID_MENU_SAVE_PREVMEM
, wxT("Save previous memory..."));
645 filemenu
->Append(wxID_MENU_SAVE_SET
, wxT("Save set of addresses..."));
646 filemenu
->Append(wxID_MENU_SAVE_ALL
, wxT("Save previous memory and set of addresses..."));
647 filemenu
->AppendSeparator();
648 filemenu
->Append(wxID_MENU_LOAD
, wxT("Load save..."));
649 menubar
->Append(filemenu
, wxT("File"));
650 wxMenu
* editmenu
= new wxMenu();
651 undoitem
= editmenu
->Append(wxID_UNDO
, wxT("Undo"));
652 redoitem
= editmenu
->Append(wxID_REDO
, wxT("Redo"));
653 undoitem
->Enable(false);
654 redoitem
->Enable(false);
655 menubar
->Append(editmenu
, wxT("Edit"));
656 Connect(wxID_MENU_DUMP_CANDIDATES
, wxEVT_COMMAND_MENU_SELECTED
,
657 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
658 Connect(wxID_MENU_SAVE_PREVMEM
, wxEVT_COMMAND_MENU_SELECTED
,
659 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
660 Connect(wxID_MENU_SAVE_SET
, wxEVT_COMMAND_MENU_SELECTED
,
661 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
662 Connect(wxID_MENU_SAVE_ALL
, wxEVT_COMMAND_MENU_SELECTED
,
663 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
664 Connect(wxID_MENU_LOAD
, wxEVT_COMMAND_MENU_SELECTED
,
665 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
666 Connect(wxID_UNDO
, wxEVT_COMMAND_MENU_SELECTED
,
667 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
668 Connect(wxID_REDO
, wxEVT_COMMAND_MENU_SELECTED
,
669 wxCommandEventHandler(wxwindow_memorysearch::on_button_click
));
673 matches
->Connect(wxEVT_LEFT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
674 matches
->Connect(wxEVT_LEFT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
675 matches
->Connect(wxEVT_MIDDLE_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
676 matches
->Connect(wxEVT_MIDDLE_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
677 matches
->Connect(wxEVT_RIGHT_DOWN
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
678 matches
->Connect(wxEVT_RIGHT_UP
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
679 matches
->Connect(wxEVT_MOTION
, wxMouseEventHandler(wxwindow_memorysearch::on_mousedrag
), NULL
, this);
680 matches
->Connect(wxEVT_MOUSEWHEEL
, wxMouseEventHandler(wxwindow_memorysearch::on_mouse
), NULL
, this);
681 scroll
->set_handler([this](scroll_bar
& s
) { this->matches
->request_paint(); });
683 toplevel
->SetSizeHints(this);
690 wxwindow_memorysearch::panel::panel(wxwindow_memorysearch
* _parent
)
691 : text_framebuffer_panel(_parent
, 40, 25, wxID_ANY
, NULL
)
698 void wxwindow_memorysearch::panel::prepare_paint()
700 uint64_t first
= parent
->scroll
->get_position();
701 auto ssize
= get_characters();
702 uint64_t last
= first
+ ssize
.second
;
703 std::vector
<std::string
> lines
;
704 lines
.reserve(ssize
.second
);
705 std::map
<uint64_t, uint64_t> addrs
;
706 auto* ms
= parent
->msearch
;
708 bool toomany
= false;
709 auto _parent
= parent
;
710 runemufn([&toomany
, &first
, &last
, ms
, &lines
, &addrs
, &addr_count
, _parent
]() {
711 addr_count
= ms
->get_candidate_count();
712 if(last
> addr_count
) {
713 uint64_t delta
= last
- addr_count
;
722 if(addr_count
<= CANDIDATE_LIMIT
) {
723 std::list
<uint64_t> addrs2
= ms
->get_candidates();
725 for(auto i
: addrs2
) {
726 std::string row
= hexformat_address(i
) + " ";
727 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, false);
729 row
+= (_parent
->*displays
[_parent
->typecode
])(i
, _parent
->hexmode
, true);
731 if(j
>= first
&& j
< last
)
732 lines
.push_back(row
);
736 lines
.push_back("Too many candidates to display");
740 std::swap(parent
->addresses
, addrs
);
742 std::ostringstream x
;
743 x
<< addr_count
<< " " << ((addr_count
!= 1) ? "candidates" : "candidate");
744 parent
->count
->SetLabel(towxstring(x
.str()));
747 for(unsigned i
= 0; i
< lines
.size(); i
++) {
748 bool sel
= (first
+ i
) >= first_sel
&& (first
+ i
) < last_sel
;
749 write(lines
[i
], 0, 0, i
, sel
? 0xFFFFFF : 0, sel
? 0 : 0xFFFFFF);
757 parent
->toomany
= toomany
;
758 parent
->scroll
->set_range(toomany
? 0 : addr_count
);
761 void wxwindow_memorysearch::panel::set_selection(uint64_t first
, uint64_t last
)
768 void wxwindow_memorysearch::panel::get_selection(uint64_t& first
, uint64_t& last
)
774 wxwindow_memorysearch::~wxwindow_memorysearch()
780 bool wxwindow_memorysearch::ShouldPreventAppExit() const
785 void wxwindow_memorysearch::dump_candidates_text()
788 std::string filename
= choose_file_save(this, "Dump memory search", project_otherpath(),
790 std::ofstream
out(filename
);
792 runemufn([ms
, this, &out
]() {
793 std::list
<uint64_t> addrs2
= ms
->get_candidates();
795 for(auto i
: addrs2
) {
796 std::string row
= hexformat_address(i
) + " ";
797 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, false);
799 row
+= (this->*displays
[this->typecode
])(i
, this->hexmode
, true);
801 out
<< row
<< std::endl
;
805 throw std::runtime_error("Can't write save file");
806 } catch(canceled_exception
& e
) {
807 } catch(std::exception
& e
) {
808 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
813 void wxwindow_memorysearch::handle_save(memory_search::savestate_type type
)
816 std::vector
<char> state
;
817 msearch
->savestate(state
, type
);
818 std::string filename
= choose_file_save(this, "Save memory search", project_otherpath(),
819 filetype_memorysearch
);
820 std::ofstream
out(filename
, std::ios::binary
);
821 out
.write(&state
[0], state
.size());
823 throw std::runtime_error("Can't write save file");
824 } catch(canceled_exception
& e
) {
825 } catch(std::exception
& e
) {
826 show_message_ok(this, "Save error", std::string(e
.what()), wxICON_WARNING
);
831 void wxwindow_memorysearch::handle_load()
834 std::string filename
= choose_file_load(this, "Load memory search", project_otherpath(),
835 filetype_memorysearch
);
836 std::vector
<char> state
= read_file_relative(filename
, "");
838 msearch
->loadstate(state
);
840 } catch(canceled_exception
& e
) {
841 } catch(std::exception
& e
) {
842 show_message_ok(this, "Load error", std::string(e
.what()), wxICON_WARNING
);
847 void wxwindow_memorysearch::handle_undo_redo(bool redo
)
849 std::list
<std::vector
<char>>& a
= *(redo
? &redohistory
: &undohistory
);
850 std::list
<std::vector
<char>>& b
= *(redo
? &undohistory
: &redohistory
);
852 show_message_ok(this, "Undo/Redo error", "Can't find state to undo/redo to", wxICON_WARNING
);
857 std::vector
<char> state
;
858 msearch
->savestate(state
, memory_search::ST_SET
);
861 msearch
->loadstate(a
.back());
863 } catch(std::exception
& e
) {
866 show_message_ok(this, "Undo/Redo error", std::string(e
.what()), wxICON_WARNING
);
869 undoitem
->Enable(undohistory
.size());
870 redoitem
->Enable(redohistory
.size());
874 void wxwindow_memorysearch::push_undo()
877 std::vector
<char> state
;
878 msearch
->savestate(state
, memory_search::ST_SET
);
879 undohistory
.push_back(state
);
880 if(undohistory
.size() > UNDOHISTORY_MAXSIZE
)
881 undohistory
.pop_front();
883 undoitem
->Enable(undohistory
.size());
884 redoitem
->Enable(redohistory
.size());
889 void wxwindow_memorysearch::on_mouse(wxMouseEvent
& e
)
891 if(e
.RightUp() || (e
.LeftUp() && e
.ControlDown()))
893 else if(e
.LeftDown())
900 if(e
.ShiftDown() && e
.ControlDown())
902 scroll
->apply_wheel(e
.GetWheelRotation(), e
.GetWheelDelta(), speed
);
905 void wxwindow_memorysearch::on_mouse0(wxMouseEvent
& e
, bool polarity
)
907 dragging
= polarity
&& !toomany
;
911 uint64_t first
= scroll
->get_position();
912 drag_startline
= first
+ e
.GetY() / matches
->get_cell().second
;
913 } else if(mpx
== e
.GetX() && mpy
== e
.GetY()) {
914 matches
->set_selection(0, 0);
918 void wxwindow_memorysearch::on_mousedrag(wxMouseEvent
& e
)
922 uint64_t first
= scroll
->get_position();
923 uint64_t linenow
= first
+ e
.GetY() / matches
->get_cell().second
;
924 if(drag_startline
< linenow
)
925 matches
->set_selection(drag_startline
, linenow
+ 1);
927 matches
->set_selection(linenow
, drag_startline
+ 1);
930 void wxwindow_memorysearch::on_mouse2(wxMouseEvent
& e
)
934 uint64_t selcount
= 0;
936 matches
->get_selection(start
, end
);
937 some_selected
= (start
< end
);
939 uint64_t first
= scroll
->get_position();
940 act_line
= first
+ e
.GetY() / matches
->get_cell().second
;
941 if(addresses
.count(act_line
)) {
942 some_selected
= true;
946 menu
.Append(wxID_ADD
, wxT("Add watch..."))->Enable(some_selected
);
947 menu
.Append(wxID_SHOW_HEXEDITOR
, wxT("Select in hex editor"))->Enable(selcount
== 1 &&
948 wxeditor_hexeditor_available());
949 menu
.Append(wxID_POKE
, wxT("Poke..."))->Enable(selcount
== 1);
950 menu
.AppendSeparator();
951 menu
.Append(wxID_DISQUALIFY
, wxT("Disqualify"))->Enable(some_selected
);
952 menu
.AppendSeparator();
953 menu
.Append(wxID_UPDATE
, wxT("Update"));
954 menu
.Append(wxID_SET_REGIONS
, wxT("Enabled VMAs"));
955 menu
.Connect(wxEVT_COMMAND_MENU_SELECTED
, wxCommandEventHandler(wxwindow_memorysearch::on_button_click
),
960 void wxwindow_memorysearch::on_close(wxCloseEvent
& e
)
966 void wxwindow_memorysearch::auto_update()
968 if(autoupdate
->GetValue())
972 void wxwindow_memorysearch::update()
974 matches
->request_paint();
977 void wxwindow_memorysearch::on_button_click(wxCommandEvent
& e
)
980 if(id
== wxID_RESET
) {
983 for(auto i
: lsnes_memory
.get_regions())
984 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
985 msearch
->dq_range(i
->base
, i
->last_address());
986 wxeditor_hexeditor_update();
987 } else if(id
== wxID_UPDATE
) {
989 } else if(id
== wxID_TYPESELECT
) {
990 wxString c
= type
->GetValue();
991 for(unsigned i
= 0; i
< DATATYPES
; i
++)
992 if(c
== towxstring(datatypes
[i
]))
994 } else if(id
== wxID_HEX_SELECT
) {
995 hexmode
= hexmode2
->GetValue();
996 } else if(id
== wxID_ADD
) {
998 matches
->get_selection(start
, end
);
1003 char wch
= watchchars
[typecode
];
1004 for(long r
= start
; r
< end
; r
++) {
1005 if(!addresses
.count(r
))
1007 uint64_t addr
= addresses
[r
];
1009 std::string n
= pick_text(this, "Name for watch", (stringfmt()
1010 << "Enter name for watch at 0x" << std::hex
<< addr
<< ":").str());
1013 std::string e
= (stringfmt() << "C0x" << std::hex
<< addr
<< "z" << wch
).str();
1014 runemufn([n
, e
]() { set_watchexpr_for(n
, e
); });
1015 } catch(canceled_exception
& e
) {
1018 matches
->set_selection(0, 0);
1019 } else if(id
== wxID_DISQUALIFY
) {
1020 uint64_t start
, end
;
1021 matches
->get_selection(start
, end
);
1027 for(long r
= start
; r
< end
; r
++) {
1028 if(!addresses
.count(r
))
1030 uint64_t addr
= addresses
[r
];
1032 runemufn([addr
, ms
]() { ms
->dq_range(addr
, addr
); });
1034 matches
->set_selection(0, 0);
1035 wxeditor_hexeditor_update();
1036 } else if(id
== wxID_SET_REGIONS
) {
1037 wxwindow_memorysearch_vmasel
* d
= new wxwindow_memorysearch_vmasel(this, vmas_enabled
);
1038 if(d
->ShowModal() == wxID_OK
)
1039 vmas_enabled
= d
->get_vmas();
1046 for(auto i
: lsnes_memory
.get_regions())
1047 if(memory_search::searchable_region(i
) && !vmas_enabled
.count(i
->name
))
1048 msearch
->dq_range(i
->base
, i
->last_address());
1049 wxeditor_hexeditor_update();
1050 } else if(id
== wxID_POKE
) {
1051 uint64_t start
, end
;
1052 matches
->get_selection(start
, end
);
1057 for(long r
= start
; r
< end
; r
++) {
1058 if(!addresses
.count(r
))
1060 uint64_t addr
= addresses
[r
];
1062 (this->*(pokes
[typecode
]))(addr
);
1063 } catch(canceled_exception
& e
) {
1067 } else if(id
== wxID_SHOW_HEXEDITOR
) {
1068 uint64_t start
, end
;
1069 matches
->get_selection(start
, end
);
1074 for(long r
= start
; r
< end
; r
++) {
1075 if(!addresses
.count(r
))
1077 wxeditor_hexeditor_jumpto(addresses
[r
]);
1080 } else if(id
>= wxID_BUTTONS_BASE
&& id
< wxID_BUTTONS_BASE
+ (sizeof(searchtbl
)/sizeof(searchtbl
[0]))) {
1081 int button
= id
- wxID_BUTTONS_BASE
;
1083 uint64_t old_count
= msearch
->get_candidate_count();
1084 (this->*(searchtbl
[button
].searches
[typecode
]))();
1085 uint64_t new_count
= msearch
->get_candidate_count();
1086 if(old_count
== new_count
) {
1087 undohistory
.pop_back(); //Shouldn't be undoable.
1088 undoitem
->Enable(undohistory
.size());
1090 wxeditor_hexeditor_update();
1091 } else if(id
== wxID_MENU_DUMP_CANDIDATES
) {
1092 dump_candidates_text();
1093 } else if(id
== wxID_MENU_SAVE_PREVMEM
) {
1094 handle_save(memory_search::ST_PREVMEM
);
1095 } else if(id
== wxID_MENU_SAVE_SET
) {
1096 handle_save(memory_search::ST_SET
);
1097 } else if(id
== wxID_MENU_SAVE_ALL
) {
1098 handle_save(memory_search::ST_ALL
);
1099 } else if(id
== wxID_MENU_LOAD
) {
1101 } else if(id
== wxID_UNDO
) {
1102 handle_undo_redo(false);
1103 } else if(id
== wxID_REDO
) {
1104 handle_undo_redo(true);
1109 template<typename T
> void wxwindow_memorysearch::_do_poke_addr(uint64_t addr
)
1111 T val
= msearch
->v_read
<T
>(addr
);
1114 v
= pick_text(this, "Poke value", (stringfmt() << "Enter value to poke to " << std::hex
<< "0x"
1115 << addr
).str(), (stringfmt() << val
).str(), false);
1116 val
= parse_value
<T
>(v
);
1117 } catch(canceled_exception
& e
) {
1120 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1123 msearch
->v_write
<T
>(addr
, val
);
1126 template<void(memory_search::*sfn
)()> void wxwindow_memorysearch::search_0()
1131 template<typename T
, typename T2
, void(memory_search::*sfn
)(T2 val
)> void wxwindow_memorysearch::search_1()
1134 T val
= promptvalue
<T
>(bad
);
1137 (msearch
->*sfn
)(static_cast<T2
>(val
));
1140 template<typename T
> T
wxwindow_memorysearch::promptvalue(bool& bad
)
1143 wxTextEntryDialog
* d
= new wxTextEntryDialog(this, wxT("Enter value to search for:"), wxT("Memory search"),
1145 if(d
->ShowModal() == wxID_CANCEL
) {
1149 v
= tostdstring(d
->GetValue());
1153 val2
= parse_value
<T
>(v
);
1155 wxMessageBox(towxstring("Bad value '" + v
+ "'"), _T("Error"), wxICON_WARNING
| wxOK
, this);
1162 void wxwindow_memorysearch_display()
1168 mwatch
= new wxwindow_memorysearch();
1172 void wxwindow_memorysearch_update()
1175 mwatch
->auto_update();
1178 memory_search
* wxwindow_memorysearch_active()
1181 return mwatch
->msearch
;