1 #include "core/moviedata.hpp"
2 #include "core/memorywatch.hpp"
4 #include "platform/wxwidgets/platform.hpp"
8 #include <wx/control.h>
9 #include <wx/combobox.h>
10 #include <wx/radiobut.h>
12 #include "library/string.hpp"
13 #include "interface/romtype.hpp"
15 class wxeditor_watchexpr
: public wxDialog
18 wxeditor_watchexpr(wxWindow
* parent
, const std::string
& name
, const std::string
& expr
);
19 bool ShouldPreventAppExit() const;
20 void on_ok(wxCommandEvent
& e
);
21 void on_cancel(wxCommandEvent
& e
);
22 void on_rb_structured(wxCommandEvent
& e
);
23 void on_rb_arbitrary(wxCommandEvent
& e
);
24 void on_rb_busaddr(wxCommandEvent
& e
);
25 void on_rb_mapaddr(wxCommandEvent
& e
);
26 void on_addr_change(wxCommandEvent
& e
);
27 std::string
get_expr();
30 wxRadioButton
* structured
;
31 wxRadioButton
* arbitrary
;
33 wxRadioButton
* busaddr
;
34 wxRadioButton
* mapaddr
;
42 int memorywatch_recognize_typech(char ch
)
61 wxeditor_watchexpr::wxeditor_watchexpr(wxWindow
* parent
, const std::string
& name
, const std::string
& expr
)
62 : wxDialog(parent
, wxID_ANY
, towxstring("lsnes: Edit watch " + name
), wxDefaultPosition
, wxSize(-1, -1))
65 wxT("Signed byte"), wxT("Unsigned byte"), wxT("Signed word"), wxT("Unsigned word"),
66 wxT("Signed onehalfword"), wxT("Unsigned onehalfword"), wxT("Signed doubleword"),
67 wxT("Unsigned doubleword"), wxT("Signed quadword"), wxT("Unsigned quadword"),
68 wxT("Float"), wxT("double")
72 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(9, 1, 0, 0);
75 top_s
->Add(structured
= new wxRadioButton(this, wxID_ANY
, wxT("Value"), wxDefaultPosition
, wxDefaultSize
,
76 wxRB_GROUP
), 0, wxGROW
);
77 top_s
->Add(arbitrary
= new wxRadioButton(this, wxID_ANY
, wxT("Expression"), wxDefaultPosition
, wxDefaultSize
,
79 top_s
->Add(typesel
= new wxComboBox(this, wxID_ANY
, types
[0], wxDefaultPosition
, wxDefaultSize
,
80 12, types
, wxCB_READONLY
), 0, wxGROW
);
81 top_s
->Add(busaddr
= new wxRadioButton(this, wxID_ANY
, wxT("Bus address"), wxDefaultPosition
, wxDefaultSize
,
82 wxRB_GROUP
), 0, wxGROW
);
83 top_s
->Add(mapaddr
= new wxRadioButton(this, wxID_ANY
, wxT("Map address"), wxDefaultPosition
, wxDefaultSize
,
85 top_s
->Add(addr
= new wxTextCtrl(this, wxID_ANY
, towxstring(""), wxDefaultPosition
, wxSize(200, -1)), 0,
87 top_s
->Add(hex
= new wxCheckBox(this, wxID_ANY
, towxstring("Hex formatting")), 0, wxGROW
);
88 top_s
->Add(watchtxt
= new wxTextCtrl(this, wxID_ANY
, towxstring(expr
), wxDefaultPosition
, wxSize(400, -1)), 1,
90 structured
->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED
,
91 wxCommandEventHandler(wxeditor_watchexpr::on_rb_structured
), NULL
, this);
92 arbitrary
->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED
,
93 wxCommandEventHandler(wxeditor_watchexpr::on_rb_arbitrary
), NULL
, this);
94 busaddr
->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED
,
95 wxCommandEventHandler(wxeditor_watchexpr::on_rb_busaddr
), NULL
, this);
96 mapaddr
->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED
,
97 wxCommandEventHandler(wxeditor_watchexpr::on_rb_mapaddr
), NULL
, this);
98 addr
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
99 wxCommandEventHandler(wxeditor_watchexpr::on_addr_change
), NULL
, this);
100 addr
->SetMaxLength(16);
101 watchtxt
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
102 wxCommandEventHandler(wxeditor_watchexpr::on_addr_change
), NULL
, this);
104 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
105 pbutton_s
->AddStretchSpacer();
106 pbutton_s
->Add(ok
= new wxButton(this, wxID_ANY
, wxT("Ok")), 0, wxGROW
);
107 pbutton_s
->Add(cancel
= new wxButton(this, wxID_ANY
, wxT("Cancel")), 0, wxGROW
);
108 ok
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
109 wxCommandEventHandler(wxeditor_watchexpr::on_ok
), NULL
, this);
110 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
111 wxCommandEventHandler(wxeditor_watchexpr::on_cancel
), NULL
, this);
112 top_s
->Add(pbutton_s
);
114 pbutton_s
->SetSizeHints(this);
115 top_s
->SetSizeHints(this);
120 structured
->SetValue(true);
121 busaddr
->SetValue(our_rom
.rtype
->get_bus_map().second
);
122 mapaddr
->SetValue(!our_rom
.rtype
->get_bus_map().second
);
123 busaddr
->Enable(our_rom
.rtype
->get_bus_map().second
);
125 } else if(r
= regex("C0x([0-9A-Fa-f]{1,16})z([bBwWdDqQ])(H([0-9A-Ga-g]))?", expr
)) {
126 structured
->SetValue(true);
127 mapaddr
->SetValue(true);
128 busaddr
->Enable(our_rom
.rtype
->get_bus_map().second
);
130 std::string addr2
= r
[1];
133 std::copy(addr2
.begin(), addr2
.end(), buf
);
134 uint64_t parsed
= strtoull(buf
, &end
, 16);
135 auto r2
= our_rom
.rtype
->get_bus_map();
136 if(parsed
>= r2
.first
&& parsed
< r2
.first
+ r2
.second
) {
138 busaddr
->SetValue(true);
140 addr
->SetValue(towxstring((stringfmt() << std::hex
<< parsed
).str()));
141 typesel
->SetSelection(memorywatch_recognize_typech(r
[2][0]));
142 hex
->SetValue(r
[3] != "");
144 arbitrary
->SetValue(true);
145 (our_rom
.rtype
->get_bus_map().second
? busaddr
: mapaddr
)->SetValue(true);
155 bool wxeditor_watchexpr::ShouldPreventAppExit() const
160 void wxeditor_watchexpr::on_ok(wxCommandEvent
& e
)
162 const char* letters
= "bBwWoOdDqQfF";
163 const char* hexwidths
= "22446688GGGG";
164 if(structured
->GetValue()) {
166 std::string addr2
= tostdstring(addr
->GetValue());
168 uint64_t parsed
= strtoull(addr2
.c_str(), &end
, 16);
169 if(busaddr
->GetValue())
170 parsed
+= our_rom
.rtype
->get_bus_map().first
;
172 hexmod
= std::string("H") + hexwidths
[typesel
->GetSelection()];
173 out
= (stringfmt() << "C0x" << std::hex
<< parsed
<< "z" << letters
[typesel
->GetSelection()]
176 out
= tostdstring(watchtxt
->GetValue());
180 void wxeditor_watchexpr::on_cancel(wxCommandEvent
& e
)
182 EndModal(wxID_CANCEL
);
185 void wxeditor_watchexpr::on_rb_arbitrary(wxCommandEvent
& e
)
196 void wxeditor_watchexpr::on_rb_structured(wxCommandEvent
& e
)
199 busaddr
->Enable(our_rom
.rtype
->get_bus_map().second
);
207 void wxeditor_watchexpr::on_rb_busaddr(wxCommandEvent
& e
)
212 void wxeditor_watchexpr::on_rb_mapaddr(wxCommandEvent
& e
)
217 void wxeditor_watchexpr::on_addr_change(wxCommandEvent
& e
)
219 if(structured
->GetValue()) {
220 std::string addr2
= tostdstring(addr
->GetValue());
221 if(!regex_match("[0-9A-Fa-f]{1,16}", addr2
)) {
226 uint64_t parsed
= strtoull(addr2
.c_str(), &end
, 16);
227 if(busaddr
->GetValue() && parsed
>= our_rom
.rtype
->get_bus_map().second
) {
233 ok
->Enable(tostdstring(watchtxt
->GetValue()) != "");
237 std::string
wxeditor_watchexpr::get_expr()
243 std::string
memorywatch_edit_watchexpr(wxWindow
* parent
, const std::string
& name
, const std::string
& expr
)
245 wxeditor_watchexpr
* d
= new wxeditor_watchexpr(parent
, name
, expr
);
246 if(d
->ShowModal() != wxID_OK
) {
248 throw canceled_exception();
250 std::string out
= d
->get_expr();
255 class wxeditor_memorywatch
: public wxDialog
258 wxeditor_memorywatch(wxWindow
* parent
);
259 bool ShouldPreventAppExit() const;
260 void on_memorywatch_change(wxCommandEvent
& e
);
261 void on_new(wxCommandEvent
& e
);
262 void on_rename(wxCommandEvent
& e
);
263 void on_delete(wxCommandEvent
& e
);
264 void on_edit(wxCommandEvent
& e
);
265 void on_close(wxCommandEvent
& e
);
270 wxButton
* renamebutton
;
271 wxButton
* deletebutton
;
272 wxButton
* editbutton
;
273 wxButton
* closebutton
;
277 wxeditor_memorywatch::wxeditor_memorywatch(wxWindow
* parent
)
278 : wxDialog(parent
, wxID_ANY
, wxT("lsnes: Edit memory watches"), wxDefaultPosition
, wxSize(-1, -1))
281 wxFlexGridSizer
* top_s
= new wxFlexGridSizer(2, 1, 0, 0);
284 top_s
->Add(watches
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxSize(400, 300)), 1, wxGROW
);
285 watches
->Connect(wxEVT_COMMAND_LISTBOX_SELECTED
,
286 wxCommandEventHandler(wxeditor_memorywatch::on_memorywatch_change
), NULL
, this);
288 wxBoxSizer
* pbutton_s
= new wxBoxSizer(wxHORIZONTAL
);
289 pbutton_s
->AddStretchSpacer();
290 pbutton_s
->Add(newbutton
= new wxButton(this, wxID_ANY
, wxT("New")), 0, wxGROW
);
291 pbutton_s
->Add(editbutton
= new wxButton(this, wxID_ANY
, wxT("Edit")), 0, wxGROW
);
292 pbutton_s
->Add(renamebutton
= new wxButton(this, wxID_ANY
, wxT("Rename")), 0, wxGROW
);
293 pbutton_s
->Add(deletebutton
= new wxButton(this, wxID_ANY
, wxT("Delete")), 0, wxGROW
);
294 pbutton_s
->Add(closebutton
= new wxButton(this, wxID_ANY
, wxT("Close")), 0, wxGROW
);
295 newbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
296 wxCommandEventHandler(wxeditor_memorywatch::on_new
), NULL
, this);
297 editbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
298 wxCommandEventHandler(wxeditor_memorywatch::on_edit
), NULL
, this);
299 renamebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
300 wxCommandEventHandler(wxeditor_memorywatch::on_rename
), NULL
, this);
301 deletebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
302 wxCommandEventHandler(wxeditor_memorywatch::on_delete
), NULL
, this);
303 closebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
304 wxCommandEventHandler(wxeditor_memorywatch::on_close
), NULL
, this);
305 top_s
->Add(pbutton_s
, 0, wxGROW
);
307 pbutton_s
->SetSizeHints(this);
308 top_s
->SetSizeHints(this);
314 bool wxeditor_memorywatch::ShouldPreventAppExit() const
319 void wxeditor_memorywatch::on_memorywatch_change(wxCommandEvent
& e
)
321 std::string watch
= tostdstring(watches
->GetStringSelection());
322 editbutton
->Enable(watch
!= "");
323 deletebutton
->Enable(watch
!= "");
324 renamebutton
->Enable(watch
!= "");
327 void wxeditor_memorywatch::on_new(wxCommandEvent
& e
)
330 std::string newname
= pick_text(this, "New watch", "Enter name for watch:");
333 std::string newtext
= memorywatch_edit_watchexpr(this, newname
, "");
335 runemufn([newname
, newtext
]() { set_watchexpr_for(newname
, newtext
); });
337 } catch(canceled_exception
& e
) {
340 on_memorywatch_change(e
);
343 void wxeditor_memorywatch::on_rename(wxCommandEvent
& e
)
345 std::string watch
= tostdstring(watches
->GetStringSelection());
350 std::string newname
= pick_text(this, "Rename watch", "Enter New name for watch:");
351 runemufn([watch
, newname
, &exists
]() {
352 std::string x
= get_watchexpr_for(watch
);
353 std::string y
= get_watchexpr_for(newname
);
357 set_watchexpr_for(watch
, "");
358 set_watchexpr_for(newname
, x
);
362 show_message_ok(this, "Error", "The target watch already exists", wxICON_EXCLAMATION
);
364 } catch(canceled_exception
& e
) {
367 on_memorywatch_change(e
);
370 void wxeditor_memorywatch::on_delete(wxCommandEvent
& e
)
372 std::string watch
= tostdstring(watches
->GetStringSelection());
374 runemufn([watch
]() { set_watchexpr_for(watch
, ""); });
376 on_memorywatch_change(e
);
379 void wxeditor_memorywatch::on_edit(wxCommandEvent
& e
)
381 std::string watch
= tostdstring(watches
->GetStringSelection());
386 runemufn([watch
, &wtxt
]() { wtxt
= get_watchexpr_for(watch
); });
387 wtxt
= memorywatch_edit_watchexpr(this, watch
, wtxt
);
389 runemufn([watch
, wtxt
]() { set_watchexpr_for(watch
, wtxt
); });
391 } catch(canceled_exception
& e
) {
394 on_memorywatch_change(e
);
397 void wxeditor_memorywatch::on_close(wxCommandEvent
& e
)
402 void wxeditor_memorywatch::refresh()
404 std::map
<std::string
, std::string
> bind
;
406 std::set
<std::string
> x
= get_watches();
408 bind
[i
] = get_watchexpr_for(i
);
412 watches
->Append(towxstring(i
.first
));
413 if(watches
->GetCount())
414 watches
->SetSelection(0);
416 on_memorywatch_change(e
);
419 void wxeditor_memorywatch_display(wxWindow
* parent
)
421 modal_pause_holder hld
;
424 editor
= new wxeditor_memorywatch(parent
);