1 #include "core/instance.hpp"
2 #include "core/moviedata.hpp"
3 #include "core/memorywatch.hpp"
4 #include "core/memorymanip.hpp"
5 #include "core/project.hpp"
7 #include "platform/wxwidgets/platform.hpp"
8 #include "platform/wxwidgets/loadsave.hpp"
11 #include <wx/statline.h>
13 #include <wx/control.h>
14 #include <wx/combobox.h>
15 #include <wx/radiobut.h>
16 #include <wx/spinctrl.h>
18 #include "library/string.hpp"
19 #include "library/hex.hpp"
20 #include "interface/romtype.hpp"
24 std::string main_expr;
26 unsigned memread_bytes; //0 if not memory read.
27 bool memread_signed_flag;
28 bool memread_float_flag;
29 int memread_endianess;
30 uint64_t memread_scale_div;
31 uint64_t memread_addr_base;
32 uint64_t memread_addr_size;
33 enum position_category {
38 std::string enabled; //Ignored for disabled.
39 std::string onscreen_xpos;
40 std::string onscreen_ypos;
41 bool onscreen_alt_origin_x;
42 bool onscreen_alt_origin_y;
43 bool onscreen_cliprange_x;
44 bool onscreen_cliprange_y;
45 std::string onscreen_font; //"" is system default.
46 int64_t onscreen_fg_color;
47 int64_t onscreen_bg_color;
48 int64_t onscreen_halo_color;
73 template<typename
... U
> label_control(wxWindow
* parent
, const std::string
& label
, U
... args
)
75 lbl
= new wxStaticText(parent
, wxID_ANY
, towxstring(label
));
76 ctrl
= new T(parent
, args
...);
83 void enable(bool state
)
88 void add(wxSizer
* s
, bool prop
= false)
90 s
->Add(lbl
, 0, wxALIGN_CENTER_VERTICAL
);
91 s
->Add(ctrl
, prop
? 1 : 0, wxGROW
);
93 void add_cb(std::function
<void(wxStaticText
* l
, T
* c
)> cb
)
97 wxStaticText
* label() { return lbl
; }
98 T
* operator->() { return ctrl
; }
104 std::string
format_color(int64_t x
)
106 return framebuffer::color::stringify(x
);
109 int64_t get_color(std::string x
)
111 return framebuffer::color(x
).asnumber();
115 class wxeditor_memorywatch
: public wxDialog
118 wxeditor_memorywatch(wxWindow
* parent
, const std::string
& name
);
119 bool ShouldPreventAppExit() const;
120 void on_position_change(wxCommandEvent
& e
);
121 void on_fontsel(wxCommandEvent
& e
);
122 void on_ok(wxCommandEvent
& e
);
123 void on_cancel(wxCommandEvent
& e
);
124 void enable_condenable2(wxCommandEvent
& e
);
126 void enable_for_pos(memwatch_printer::position_category p
);
127 void enable_for_addr(bool is_addr
);
128 void enable_for_vma(bool free
, uint64_t _base
, uint64_t _size
);
129 void enable_condenable();
130 memwatch_printer::position_category
get_poscategory();
131 label_control
<wxComboBox
> type
;
132 label_control
<wxTextCtrl
> expr
;
133 label_control
<wxTextCtrl
> format
;
134 label_control
<wxComboBox
> endianess
;
135 label_control
<wxSpinCtrl
> scale
;
136 label_control
<wxComboBox
> vma
;
137 label_control
<wxTextCtrl
> addrbase
;
138 label_control
<wxTextCtrl
> addrsize
;
139 label_control
<wxComboBox
> position
;
140 wxCheckBox
* cond_enable
;
142 label_control
<wxTextCtrl
> xpos
;
143 label_control
<wxTextCtrl
> ypos
;
144 wxCheckBox
* alt_origin_x
;
145 wxCheckBox
* alt_origin_y
;
146 wxCheckBox
* cliprange_x
;
147 wxCheckBox
* cliprange_y
;
148 label_control
<wxTextCtrl
> font
;
150 label_control
<wxTextCtrl
> fg_color
;
151 label_control
<wxTextCtrl
> bg_color
;
152 label_control
<wxTextCtrl
> halo_color
;
156 std::string old_addrbase
;
157 std::string old_addrsize
;
159 std::map
<int, std::pair
<uint64_t, uint64_t>> vmas_available
;
162 wxeditor_memorywatch::wxeditor_memorywatch(wxWindow
* parent
, const std::string
& _name
)
163 : wxDialog(parent
, wxID_ANY
, towxstring("Edit memory watch '" + _name
+ "'")), name(_name
)
166 wxSizer
* top_s
= new wxBoxSizer(wxVERTICAL
);
170 wxSizer
* s1
= new wxBoxSizer(wxHORIZONTAL
);
171 type
= label_control
<wxComboBox
>(this, "Data type", wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
, 0,
172 nullptr, wxCB_READONLY
);
174 type
->Append("(Expression)");
175 type
->Append("Signed byte");
176 type
->Append("Unsigned byte");
177 type
->Append("Signed word");
178 type
->Append("Unsigned word");
179 type
->Append("Signed 3-byte");
180 type
->Append("Unsigned 3-byte");
181 type
->Append("Signed dword");
182 type
->Append("Unsigned dword");
183 type
->Append("Float");
184 type
->Append("Signed qword");
185 type
->Append("Unsigned qword");
186 type
->Append("Double");
187 type
->SetSelection(3);
188 type
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
189 wxCommandEventHandler(wxeditor_memorywatch::on_position_change
), NULL
, this);
190 endianess
= label_control
<wxComboBox
>(this, "Endian:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
191 0, nullptr, wxCB_READONLY
);
192 endianess
.add(s1
, true);
193 endianess
->Append(wxT("Little"));
194 endianess
->Append(wxT("Host"));
195 endianess
->Append(wxT("Big"));
196 endianess
->SetSelection(0);
197 scale
= label_control
<wxSpinCtrl
>(this, "Scale bits:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
198 wxSP_ARROW_KEYS
, 0, 63, 0);
200 top_s
->Add(s1
, 1, wxGROW
);
203 wxSizer
* s5
= new wxBoxSizer(wxHORIZONTAL
);
204 vma
= label_control
<wxComboBox
>(this, "Memory:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
, 0,
205 nullptr, wxCB_READONLY
);
207 vma
->Append(wxT("(All)"));
208 auto i
= lsnes_instance
.memory
.get_regions();
210 int id
= vma
->GetCount();
211 vma
->Append(towxstring(j
->name
));
212 vmas_available
[id
] = std::make_pair(j
->base
, j
->size
);
214 vma
->SetSelection(0);
215 vma
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
216 wxCommandEventHandler(wxeditor_memorywatch::on_position_change
), NULL
, this);
217 addrbase
= label_control
<wxTextCtrl
>(this, "Base:", wxID_ANY
, wxT("0"), wxDefaultPosition
, wxSize(100, -1));
218 addrbase
.add(s5
, true);
219 addrsize
= label_control
<wxTextCtrl
>(this, "Size:", wxID_ANY
, wxT("0"), wxDefaultPosition
, wxSize(100, -1));
220 addrsize
.add(s5
, true);
221 top_s
->Add(s5
, 1, wxGROW
);
224 wxSizer
* s2
= new wxBoxSizer(wxHORIZONTAL
);
225 expr
= label_control
<wxTextCtrl
>(this, "Address:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1));
227 top_s
->Add(s2
, 1, wxGROW
);
230 wxSizer
* s3
= new wxBoxSizer(wxHORIZONTAL
);
231 format
= label_control
<wxTextCtrl
>(this, "Format:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1));
232 format
.add(s3
, true);
233 top_s
->Add(s3
, 1, wxGROW
);
235 wxSizer
* sx
= new wxBoxSizer(wxVERTICAL
);
237 top_s
->Add(sx
, 0, wxGROW
);
239 wxSizer
* s6
= new wxBoxSizer(wxHORIZONTAL
);
240 position
= label_control
<wxComboBox
>(this, "Position: ", wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
241 0, nullptr, wxCB_READONLY
);
242 position
.add(s6
, true);
243 position
->Append(wxT("Disabled"));
244 position
->Append(wxT("Memory watch"));
245 position
->Append(wxT("On screen"));
246 position
->SetSelection(1);
247 position
->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED
,
248 wxCommandEventHandler(wxeditor_memorywatch::on_position_change
), NULL
, this);
249 top_s
->Add(s6
, 0, wxGROW
);
251 wxSizer
* s7
= new wxBoxSizer(wxHORIZONTAL
);
252 s7
->Add(cond_enable
= new wxCheckBox(this, wxID_ANY
, wxT("Conditional on: ")), 0, wxGROW
);
253 s7
->Add(enabled
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1, wxGROW
);
254 cond_enable
->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED
,
255 wxCommandEventHandler(wxeditor_memorywatch::enable_condenable2
), NULL
, this);
256 top_s
->Add(s7
, 0, wxGROW
);
258 wxSizer
* s8
= new wxBoxSizer(wxHORIZONTAL
);
260 xpos
= label_control
<wxTextCtrl
>(this, "X:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(300, -1));
262 s8
->Add(alt_origin_x
= new wxCheckBox(this, wxID_ANY
, wxT("Alt. origin")), 0, wxGROW
);
263 s8
->Add(cliprange_x
= new wxCheckBox(this, wxID_ANY
, wxT("Clip range")), 0, wxGROW
);
264 top_s
->Add(s8
, 0, wxGROW
);
266 wxSizer
* s9
= new wxBoxSizer(wxHORIZONTAL
);
267 ypos
= label_control
<wxTextCtrl
>(this, "Y:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(300, -1));
269 s9
->Add(alt_origin_y
= new wxCheckBox(this, wxID_ANY
, wxT("Alt. origin")), 0, wxGROW
);
270 s9
->Add(cliprange_y
= new wxCheckBox(this, wxID_ANY
, wxT("Clip range")), 0, wxGROW
);
271 top_s
->Add(s9
, 0, wxGROW
);
273 wxSizer
* s10
= new wxBoxSizer(wxHORIZONTAL
);
274 font
= label_control
<wxTextCtrl
>(this, "Font:", wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(300, -1));
276 s10
->Add(font_sel
= new wxButton(this, wxID_ANY
, wxT("...")), 0, wxGROW
);
277 font_sel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
278 wxCommandEventHandler(wxeditor_memorywatch::on_fontsel
), NULL
, this);
279 top_s
->Add(s10
, 0, wxGROW
);
281 wxSizer
* s11
= new wxBoxSizer(wxHORIZONTAL
);
282 fg_color
= label_control
<wxTextCtrl
>(this, "Foreground:", wxID_ANY
, wxT("#FFFFFF"),
283 wxDefaultPosition
, wxSize(100, -1));
284 fg_color
.add(s11
, true);
285 bg_color
= label_control
<wxTextCtrl
>(this, "Background:", wxID_ANY
, wxT("transparent"), wxDefaultPosition
,
287 bg_color
.add(s11
, true);
288 halo_color
= label_control
<wxTextCtrl
>(this, "Halo:", wxID_ANY
, wxT("transparent"), wxDefaultPosition
,
290 halo_color
.add(s11
, true);
291 top_s
->Add(s11
, 0, wxGROW
);
293 wxSizer
* s12
= new wxBoxSizer(wxHORIZONTAL
);
294 s12
->AddStretchSpacer();
295 s12
->Add(ok
= new wxButton(this, wxID_ANY
, wxT("Ok")), 0, wxGROW
);
296 ok
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxeditor_memorywatch::on_ok
), NULL
, this);
297 s12
->Add(cancel
= new wxButton(this, wxID_ANY
, wxT("Cancel")), 0, wxGROW
);
298 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxeditor_memorywatch::on_cancel
), NULL
,
300 top_s
->Add(s12
, 0, wxGROW
);
302 memwatch_item
it(lsnes_instance
.memory
);
305 it
= lsnes_instance
.mwatch
.get(name
);
310 expr
->SetValue(towxstring(it
.expr
));
311 format
->SetValue(towxstring(it
.format
));
312 cond_enable
->SetValue(it
.printer
.cond_enable
);
313 enabled
->SetValue(it
.printer
.enabled
);
314 xpos
->SetValue(it
.printer
.onscreen_xpos
);
315 ypos
->SetValue(it
.printer
.onscreen_ypos
);
316 alt_origin_x
->SetValue(it
.printer
.onscreen_alt_origin_x
);
317 alt_origin_y
->SetValue(it
.printer
.onscreen_alt_origin_y
);
318 cliprange_x
->SetValue(it
.printer
.onscreen_cliprange_x
);
319 cliprange_y
->SetValue(it
.printer
.onscreen_cliprange_y
);
320 endianess
->SetSelection(it
.endianess
+ 1);
321 addrbase
->SetValue(towxstring(hex::to
<uint64_t>(it
.addr_base
)));
322 addrsize
->SetValue(towxstring(hex::to
<uint64_t>(it
.addr_size
)));
323 if(it
.printer
.position
== memwatch_printer::PC_DISABLED
) position
->SetSelection(0);
324 if(it
.printer
.position
== memwatch_printer::PC_MEMORYWATCH
) position
->SetSelection(1);
325 if(it
.printer
.position
== memwatch_printer::PC_ONSCREEN
) position
->SetSelection(2);
327 case 0: type
->SetSelection(0); break;
328 case 1: type
->SetSelection(it
.signed_flag
? 1 : 2); break;
329 case 2: type
->SetSelection(it
.signed_flag
? 3 : 4); break;
330 case 3: type
->SetSelection(it
.signed_flag
? 5 : 6); break;
331 case 4: type
->SetSelection(it
.float_flag
? 9 : (it
.signed_flag
? 7 : 8)); break;
332 case 8: type
->SetSelection(it
.float_flag
? 12 : (it
.signed_flag
? 11 : 10)); break;
334 scale
->SetValue(log2i(it
.scale_div
));
335 for(auto j
: vmas_available
) {
336 if(j
.second
.first
== it
.addr_base
&& j
.second
.second
== it
.addr_size
)
337 vma
->SetSelection(j
.first
);
339 font
->SetValue(it
.printer
.onscreen_font
);
340 fg_color
->SetValue(towxstring(format_color(it
.printer
.onscreen_fg_color
)));
341 bg_color
->SetValue(towxstring(format_color(it
.printer
.onscreen_bg_color
)));
342 halo_color
->SetValue(towxstring(format_color(it
.printer
.onscreen_halo_color
)));
346 on_position_change(e
);
347 top_s
->SetSizeHints(this);
351 bool wxeditor_memorywatch::ShouldPreventAppExit() const
356 memwatch_printer::position_category
wxeditor_memorywatch::get_poscategory()
358 if(position
->GetSelection() == 0) return memwatch_printer::PC_DISABLED
;
359 if(position
->GetSelection() == 1) return memwatch_printer::PC_MEMORYWATCH
;
360 if(position
->GetSelection() == 2) return memwatch_printer::PC_ONSCREEN
;
361 return memwatch_printer::PC_DISABLED
; //NOTREACHED.
364 void wxeditor_memorywatch::enable_for_pos(memwatch_printer::position_category p
)
366 bool full_disable
= (p
== memwatch_printer::PC_DISABLED
);
367 cond_enable
->Enable(!full_disable
);
368 enabled
->Enable(cond_enable
->GetValue() && !full_disable
);
369 xpos
.enable(p
== memwatch_printer::PC_ONSCREEN
);
370 ypos
.enable(p
== memwatch_printer::PC_ONSCREEN
);
371 alt_origin_x
->Enable(p
== memwatch_printer::PC_ONSCREEN
);
372 alt_origin_y
->Enable(p
== memwatch_printer::PC_ONSCREEN
);
373 cliprange_x
->Enable(p
== memwatch_printer::PC_ONSCREEN
);
374 cliprange_y
->Enable(p
== memwatch_printer::PC_ONSCREEN
);
375 font
.enable(p
== memwatch_printer::PC_ONSCREEN
);
376 font_sel
->Enable(p
== memwatch_printer::PC_ONSCREEN
);
377 fg_color
.enable(p
== memwatch_printer::PC_ONSCREEN
);
378 bg_color
.enable(p
== memwatch_printer::PC_ONSCREEN
);
379 halo_color
.enable(p
== memwatch_printer::PC_ONSCREEN
);
382 void wxeditor_memorywatch::enable_condenable()
384 memwatch_printer::position_category p
= get_poscategory();
385 bool full_disable
= (p
== memwatch_printer::PC_DISABLED
);
386 enabled
->Enable(cond_enable
->GetValue() && !full_disable
);
389 void wxeditor_memorywatch::enable_condenable2(wxCommandEvent
& e
)
394 void wxeditor_memorywatch::enable_for_addr(bool is_addr
)
396 expr
.label()->SetLabel(towxstring(is_addr
? "Address:" : "Expr:"));
397 endianess
.enable(is_addr
);
398 scale
.enable(is_addr
);
400 addrbase
.enable(is_addr
&& was_free
);
401 addrsize
.enable(is_addr
&& was_free
);
405 void wxeditor_memorywatch::enable_for_vma(bool free
, uint64_t _base
, uint64_t _size
)
407 //TODO: Set default endian.
408 if(!free
&& !was_free
) {
409 addrbase
->SetValue(towxstring((stringfmt() << std::hex
<< _base
).str()));
410 addrsize
->SetValue(towxstring((stringfmt() << std::hex
<< _size
).str()));
411 } else if(free
&& !was_free
) {
412 addrbase
->SetValue(towxstring(old_addrbase
));
413 addrsize
->SetValue(towxstring(old_addrsize
));
414 addrbase
.enable(true);
415 addrsize
.enable(true);
416 } else if(!free
&& was_free
) {
417 old_addrbase
= tostdstring(addrbase
->GetValue());
418 old_addrsize
= tostdstring(addrsize
->GetValue());
419 addrbase
->SetValue(towxstring((stringfmt() << std::hex
<< _base
).str()));
420 addrsize
->SetValue(towxstring((stringfmt() << std::hex
<< _size
).str()));
421 addrbase
.enable(false);
422 addrsize
.enable(false);
427 void wxeditor_memorywatch::on_position_change(wxCommandEvent
& e
)
429 enable_for_pos(get_poscategory());
430 int vmasel
= vma
->GetSelection();
432 enable_for_vma(true, 0, 0);
433 else if(vmas_available
.count(vmasel
)) {
434 enable_for_vma(false, vmas_available
[vmasel
].first
, vmas_available
[vmasel
].second
);
436 vma
->SetSelection(0);
437 enable_for_vma(true, 0, 0);
439 enable_for_addr(type
->GetSelection() != 0);
442 void wxeditor_memorywatch::on_fontsel(wxCommandEvent
& e
)
445 std::string filename
= choose_file_load(this, "Choose font file", lsnes_instance
.project
.otherpath(),
447 font
->SetValue(towxstring(filename
));
448 } catch(canceled_exception
& e
) {
452 void wxeditor_memorywatch::on_ok(wxCommandEvent
& e
)
454 memwatch_item
it(lsnes_instance
.memory
);
455 it
.expr
= tostdstring(expr
->GetValue());
456 it
.format
= tostdstring(format
->GetValue());
457 it
.printer
.cond_enable
= cond_enable
->GetValue();
458 it
.printer
.enabled
= tostdstring(enabled
->GetValue());
459 it
.printer
.onscreen_xpos
= tostdstring(xpos
->GetValue());
460 it
.printer
.onscreen_ypos
= tostdstring(ypos
->GetValue());
461 it
.printer
.onscreen_alt_origin_x
= alt_origin_x
->GetValue();
462 it
.printer
.onscreen_alt_origin_y
= alt_origin_y
->GetValue();
463 it
.printer
.onscreen_cliprange_x
= cliprange_x
->GetValue();
464 it
.printer
.onscreen_cliprange_y
= cliprange_y
->GetValue();
465 it
.printer
.onscreen_font
= tostdstring(font
->GetValue());
466 it
.endianess
= endianess
->GetSelection() - 1;
468 it
.addr_base
= hex::from
<uint64_t>(tostdstring(addrbase
->GetValue()));
469 it
.addr_size
= hex::from
<uint64_t>(tostdstring(addrsize
->GetValue()));
470 } catch(std::exception
& e
) {
471 show_message_ok(NULL
, "Bad memory range", std::string("Error parsing memory range: ") + e
.what(),
475 if(position
->GetSelection() == 0) it
.printer
.position
= memwatch_printer::PC_DISABLED
;
476 else if(position
->GetSelection() == 1) it
.printer
.position
= memwatch_printer::PC_MEMORYWATCH
;
477 else if(position
->GetSelection() == 2) it
.printer
.position
= memwatch_printer::PC_ONSCREEN
;
478 else it
.printer
.position
= memwatch_printer::PC_MEMORYWATCH
;
479 it
.signed_flag
= false;
480 it
.float_flag
= false;
481 switch(type
->GetSelection()) {
482 case 0: it
.bytes
= 0; break;
483 case 1: it
.bytes
= 1; it
.signed_flag
= !false; break;
484 case 2: it
.bytes
= 1; it
.signed_flag
= !true; break;
485 case 3: it
.bytes
= 2; it
.signed_flag
= !false; break;
486 case 4: it
.bytes
= 2; it
.signed_flag
= !true; break;
487 case 5: it
.bytes
= 3; it
.signed_flag
= !false; break;
488 case 6: it
.bytes
= 3; it
.signed_flag
= !true; break;
489 case 7: it
.bytes
= 4; it
.signed_flag
= !false; break;
490 case 8: it
.bytes
= 4; it
.signed_flag
= !true; break;
491 case 9: it
.bytes
= 4; it
.float_flag
= true; break;
492 case 10: it
.bytes
= 8; it
.signed_flag
= !false; break;
493 case 11: it
.bytes
= 8; it
.signed_flag
= !true; break;
494 case 12: it
.bytes
= 8; it
.float_flag
= true; break;
496 it
.scale_div
= 1ULL << scale
->GetValue();
498 it
.printer
.onscreen_fg_color
= get_color(tostdstring(fg_color
->GetValue()));
499 it
.printer
.onscreen_bg_color
= get_color(tostdstring(bg_color
->GetValue()));
500 it
.printer
.onscreen_halo_color
= get_color(tostdstring(halo_color
->GetValue()));
501 } catch(std::exception
& e
) {
502 show_message_ok(NULL
, "Bad colors", std::string("Error parsing colors: ") + e
.what(),
506 bool did_error
= false;
508 lsnes_instance
.iqueue
.run([this, &it
, &did_error
, &error
]() {
510 lsnes_instance
.mwatch
.set(name
, it
);
511 } catch(std::exception
& e
) {
517 show_message_ok(NULL
, "Bad values", std::string("Error setting memory watch: ") + error
,
524 void wxeditor_memorywatch::on_cancel(wxCommandEvent
& e
)
526 EndModal(wxID_CANCEL
);
529 class wxeditor_memorywatches
: public wxDialog
532 wxeditor_memorywatches(wxWindow
* parent
);
533 bool ShouldPreventAppExit() const;
534 void on_memorywatch_change(wxCommandEvent
& e
);
535 void on_new(wxCommandEvent
& e
);
536 void on_rename(wxCommandEvent
& e
);
537 void on_delete(wxCommandEvent
& e
);
538 void on_edit(wxCommandEvent
& e
);
539 void on_close(wxCommandEvent
& e
);
542 //TODO: Make this a wxGrid.
545 wxButton
* renamebutton
;
546 wxButton
* deletebutton
;
547 wxButton
* editbutton
;
548 wxButton
* closebutton
;
552 wxeditor_memorywatches::wxeditor_memorywatches(wxWindow
* parent
)
553 : wxDialog(parent
, wxID_ANY
, wxT("lsnes: Edit memory watches"), wxDefaultPosition
, wxSize(-1, -1))
556 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(2, 1, 0, 0);
559 top_s
->Add(watches
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxSize(400, 300)), 1, wxGROW
);
560 watches
->Connect(wxEVT_COMMAND_LISTBOX_SELECTED
,
561 wxCommandEventHandler(wxeditor_memorywatches::on_memorywatch_change
), NULL
, this);
563 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
564 pbutton_s
->AddStretchSpacer();
565 pbutton_s
->Add(newbutton
= new wxButton(this, wxID_ANY
, wxT("New")), 0, wxGROW
);
566 pbutton_s
->Add(editbutton
= new wxButton(this, wxID_ANY
, wxT("Edit")), 0, wxGROW
);
567 pbutton_s
->Add(renamebutton
= new wxButton(this, wxID_ANY
, wxT("Rename")), 0, wxGROW
);
568 pbutton_s
->Add(deletebutton
= new wxButton(this, wxID_ANY
, wxT("Delete")), 0, wxGROW
);
569 pbutton_s
->Add(closebutton
= new wxButton(this, wxID_ANY
, wxT("Close")), 0, wxGROW
);
570 newbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
571 wxCommandEventHandler(wxeditor_memorywatches::on_new
), NULL
, this);
572 editbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
573 wxCommandEventHandler(wxeditor_memorywatches::on_edit
), NULL
, this);
574 renamebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
575 wxCommandEventHandler(wxeditor_memorywatches::on_rename
), NULL
, this);
576 deletebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
577 wxCommandEventHandler(wxeditor_memorywatches::on_delete
), NULL
, this);
578 closebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
579 wxCommandEventHandler(wxeditor_memorywatches::on_close
), NULL
, this);
580 top_s
->Add(pbutton_s
, 0, wxGROW
);
582 pbutton_s
->SetSizeHints(this);
583 top_s
->SetSizeHints(this);
589 bool wxeditor_memorywatches::ShouldPreventAppExit() const
594 void wxeditor_memorywatches::on_memorywatch_change(wxCommandEvent
& e
)
596 std::string watch
= tostdstring(watches
->GetStringSelection());
597 editbutton
->Enable(watch
!= "");
598 deletebutton
->Enable(watch
!= "");
599 renamebutton
->Enable(watch
!= "");
602 void wxeditor_memorywatches::on_new(wxCommandEvent
& e
)
605 std::string newname
= pick_text(this, "New watch", "Enter name for watch:");
608 wxeditor_memorywatch
* nwch
= new wxeditor_memorywatch(this, newname
);
612 } catch(canceled_exception
& e
) {
615 on_memorywatch_change(e
);
618 void wxeditor_memorywatches::on_rename(wxCommandEvent
& e
)
620 std::string watch
= tostdstring(watches
->GetStringSelection());
625 std::string newname
= pick_text(this, "Rename watch", "Enter New name for watch:");
626 lsnes_instance
.iqueue
.run([watch
, newname
, &exists
]() {
627 exists
= !lsnes_instance
.mwatch
.rename(watch
, newname
);
630 show_message_ok(this, "Error", "The target watch already exists", wxICON_EXCLAMATION
);
632 } catch(canceled_exception
& e
) {
635 on_memorywatch_change(e
);
638 void wxeditor_memorywatches::on_delete(wxCommandEvent
& e
)
640 std::string watch
= tostdstring(watches
->GetStringSelection());
642 lsnes_instance
.iqueue
.run([watch
]() { lsnes_instance
.mwatch
.clear(watch
); });
644 on_memorywatch_change(e
);
647 void wxeditor_memorywatches::on_edit(wxCommandEvent
& e
)
650 std::string watch
= tostdstring(watches
->GetStringSelection());
654 wxeditor_memorywatch
* ewch
= new wxeditor_memorywatch(this, watch
);
658 } catch(canceled_exception
& e
) {
661 on_memorywatch_change(e
);
664 void wxeditor_memorywatches::on_close(wxCommandEvent
& e
)
669 void wxeditor_memorywatches::refresh()
671 std::set
<std::string
> bind
;
672 lsnes_instance
.iqueue
.run([&bind
]() {
673 bind
= lsnes_instance
.mwatch
.enumerate();
677 watches
->Append(towxstring(i
));
678 if(watches
->GetCount())
679 watches
->SetSelection(0);
681 on_memorywatch_change(e
);
684 void wxeditor_memorywatches_display(wxWindow
* parent
)
686 modal_pause_holder hld
;
689 editor
= new wxeditor_memorywatches(parent
);