Support in-memory saves and use those for wxwidgets ROM loading
[lsnes.git] / src / platform / wxwidgets / romselect.cpp
blobbbf8353de8025f2c1dbc149edaf400088f831932
1 //Gaah... wx/wx.h (contains something that breaks if included after snes/snes.hpp from bsnes v085.
2 #include <wx/wx.h>
3 #include <wx/dnd.h>
4 #include <wx/statbox.h>
5 #include <wx/notebook.h>
7 #include "lsnes.hpp"
9 #include "core/controller.hpp"
10 #include "core/moviedata.hpp"
11 #include "core/moviedata.hpp"
12 #include "core/framerate.hpp"
13 #include "core/project.hpp"
14 #include "core/rom.hpp"
15 #include "core/settings.hpp"
16 #include "core/window.hpp"
17 #include "interface/romtype.hpp"
18 #include "interface/setting.hpp"
19 #include "library/string.hpp"
20 #include "library/zip.hpp"
21 #include <boost/lexical_cast.hpp>
22 #include <boost/filesystem.hpp>
24 #include "platform/wxwidgets/platform.hpp"
25 #include "platform/wxwidgets/loadsave.hpp"
28 #define ASK_SRAMS_BASE (wxID_HIGHEST + 129)
29 #define ASK_SRAMS_LAST (wxID_HIGHEST + 255)
31 namespace
33 std::string generate_project_id()
35 return (stringfmt() << time(NULL) << "_" << get_random_hexstring(4)).str();
38 class textboxloadfilename : public wxFileDropTarget
40 public:
41 textboxloadfilename(wxTextCtrl* _ctrl)
43 ctrl = _ctrl;
46 bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
48 if(filenames.Count() != 1)
49 return false;
50 ctrl->SetValue(filenames[0]);
51 return true;
53 private:
54 wxTextCtrl* ctrl;
57 struct setting_select
59 setting_select(wxWindow* parent, const core_setting& s);
60 wxWindow* get_label() { return label; }
61 wxWindow* get_control();
62 const core_setting& get_setting() { return setting; }
63 std::string read();
64 private:
65 wxStaticText* label;
66 wxTextCtrl* text;
67 wxCheckBox* check;
68 wxComboBox* combo;
69 core_setting setting;
72 setting_select::setting_select(wxWindow* parent, const core_setting& s)
73 : setting(s)
75 label = new wxStaticText(parent, wxID_ANY, towxstring(setting.hname));
76 text = NULL;
77 combo = NULL;
78 check = NULL;
79 if(setting.is_boolean()) {
80 check = new wxCheckBox(parent, wxID_ANY, towxstring(""));
81 check->SetValue(s.dflt != "0");
82 } else if(setting.is_freetext()) {
83 text = new wxTextCtrl(parent, wxID_ANY, towxstring(setting.dflt), wxDefaultPosition,
84 wxSize(400, -1));
85 } else {
86 std::vector<wxString> _hvalues;
87 std::string dflt = "";
88 for(auto i : setting.values) {
89 _hvalues.push_back(towxstring(i.hname));
90 if(i.iname == setting.dflt)
91 dflt = i.hname;
93 combo = new wxComboBox(parent, wxID_ANY, towxstring(dflt), wxDefaultPosition,
94 wxDefaultSize, _hvalues.size(), &_hvalues[0], wxCB_READONLY);
98 wxWindow* setting_select::get_control()
100 if(text) return text;
101 if(check) return check;
102 if(combo) return combo;
103 return NULL;
106 std::string setting_select::read()
108 if(text) return tostdstring(text->GetValue());
109 if(check) return check->GetValue() ? "1" : "0";
110 if(combo) return setting.hvalue_to_ivalue(tostdstring(combo->GetValue()));
111 return "";
114 class wxwin_newproject : public wxDialog
116 public:
117 wxwin_newproject(wxWindow* parent);
118 ~wxwin_newproject();
119 void on_ok(wxCommandEvent& e);
120 void on_cancel(wxCommandEvent& e);
121 void on_projname_edit(wxCommandEvent& e);
122 void on_memorywatch_select(wxCommandEvent& e);
123 void on_directory_select(wxCommandEvent& e);
124 void on_add(wxCommandEvent& e);
125 void on_remove(wxCommandEvent& e);
126 void on_up(wxCommandEvent& e);
127 void on_down(wxCommandEvent& e);
128 void on_luasel(wxCommandEvent& e);
129 private:
130 void reorder_scripts(int delta);
131 wxTextCtrl* projname;
132 wxTextCtrl* memwatch;
133 wxTextCtrl* projdir;
134 wxTextCtrl* projpfx;
135 wxListBox* luascripts;
136 wxButton* swatch;
137 wxButton* sdir;
138 wxButton* addbutton;
139 wxButton* removebutton;
140 wxButton* upbutton;
141 wxButton* downbutton;
142 wxButton* okbutton;
143 wxButton* cancel;
146 wxwin_newproject::~wxwin_newproject()
150 wxwin_newproject::wxwin_newproject(wxWindow* parent)
151 : wxDialog(parent, wxID_ANY, wxT("New Project"), wxDefaultPosition, wxSize(-1, -1),
152 wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX)
154 Centre();
155 wxBoxSizer* toplevel = new wxBoxSizer(wxVERTICAL);
156 SetSizer(toplevel);
158 wxFlexGridSizer* c_s = new wxFlexGridSizer(1, 2, 0, 0);
159 c_s->Add(new wxStaticText(this, wxID_ANY, wxT("Project name:")), 0, wxGROW);
160 c_s->Add(projname = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)), 1,
161 wxGROW);
162 projname->Connect(wxEVT_COMMAND_TEXT_UPDATED,
163 wxCommandEventHandler(wxwin_newproject::on_projname_edit), NULL, this);
164 toplevel->Add(c_s);
166 wxFlexGridSizer* c4_s = new wxFlexGridSizer(1, 3, 0, 0);
167 c4_s->Add(new wxStaticText(this, wxID_ANY, wxT("Directory:")), 0, wxGROW);
168 c4_s->Add(projdir = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)), 1,
169 wxGROW);
170 projdir->Connect(wxEVT_COMMAND_TEXT_UPDATED,
171 wxCommandEventHandler(wxwin_newproject::on_projname_edit), NULL, this);
172 c4_s->Add(sdir = new wxButton(this, wxID_ANY, wxT("...")), 1, wxGROW);
173 sdir->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
174 wxCommandEventHandler(wxwin_newproject::on_directory_select), NULL, this);
175 toplevel->Add(c4_s);
177 wxFlexGridSizer* c5_s = new wxFlexGridSizer(1, 2, 0, 0);
178 c5_s->Add(new wxStaticText(this, wxID_ANY, wxT("Prefix:")), 0, wxGROW);
179 c5_s->Add(projpfx = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)), 1,
180 wxGROW);
181 projpfx->Connect(wxEVT_COMMAND_TEXT_UPDATED,
182 wxCommandEventHandler(wxwin_newproject::on_projname_edit), NULL, this);
183 toplevel->Add(c5_s);
185 wxFlexGridSizer* c2_s = new wxFlexGridSizer(1, 3, 0, 0);
186 c2_s->Add(new wxStaticText(this, wxID_ANY, wxT("Memory watch:")), 0, wxGROW);
187 c2_s->Add(memwatch = new wxTextCtrl(this, wxID_ANY, wxT(""),
188 wxDefaultPosition, wxSize(350, -1)), 1, wxGROW);
189 wxButton* pdir;
190 c2_s->Add(swatch = new wxButton(this, wxID_ANY, wxT("...")), 1, wxGROW);
191 swatch->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
192 wxCommandEventHandler(wxwin_newproject::on_memorywatch_select), NULL, this);
193 toplevel->Add(c2_s);
195 toplevel->Add(new wxStaticText(this, wxID_ANY, wxT("Autoload lua scripts:")), 0, wxGROW);
196 toplevel->Add(luascripts = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(400, 100)), 1,
197 wxEXPAND);
198 luascripts->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
199 wxCommandEventHandler(wxwin_newproject::on_luasel), NULL, this);
201 wxFlexGridSizer* c3_s = new wxFlexGridSizer(1, 4, 0, 0);
202 c3_s->Add(addbutton = new wxButton(this, wxID_ANY, wxT("Add")), 1, wxGROW);
203 addbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
204 wxCommandEventHandler(wxwin_newproject::on_add), NULL, this);
205 c3_s->Add(removebutton = new wxButton(this, wxID_ANY, wxT("Remove")), 1, wxGROW);
206 removebutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
207 wxCommandEventHandler(wxwin_newproject::on_remove), NULL, this);
208 removebutton->Disable();
209 c3_s->Add(upbutton = new wxButton(this, wxID_ANY, wxT("Up")), 1, wxGROW);
210 upbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
211 wxCommandEventHandler(wxwin_newproject::on_up), NULL, this);
212 upbutton->Disable();
213 c3_s->Add(downbutton = new wxButton(this, wxID_ANY, wxT("Down")), 1, wxGROW);
214 downbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
215 wxCommandEventHandler(wxwin_newproject::on_down), NULL, this);
216 downbutton->Disable();
217 toplevel->Add(c3_s);
219 wxBoxSizer* buttonbar = new wxBoxSizer(wxHORIZONTAL);
220 buttonbar->Add(okbutton = new wxButton(this, wxID_ANY, wxT("OK")), 0, wxGROW);
221 buttonbar->AddStretchSpacer();
222 buttonbar->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
223 okbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
224 wxCommandEventHandler(wxwin_newproject::on_ok), NULL, this);
225 cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
226 wxCommandEventHandler(wxwin_newproject::on_cancel), NULL, this);
227 toplevel->Add(buttonbar, 0, wxGROW);
228 //This gets re-enabled later if needed.
229 okbutton->Disable();
231 toplevel->SetSizeHints(this);
232 Fit();
235 void wxwin_newproject::on_ok(wxCommandEvent& e)
237 project_info pinfo;
238 pinfo.id = generate_project_id();
239 pinfo.name = tostdstring(projname->GetValue());
240 pinfo.rom = our_rom.load_filename;
241 pinfo.last_save = "";
242 pinfo.directory = tostdstring(projdir->GetValue());
243 pinfo.prefix = tostdstring(projpfx->GetValue());
244 pinfo.gametype = our_movie.gametype->get_name();
245 pinfo.settings = our_movie.settings;
246 pinfo.coreversion = our_movie.coreversion;
247 pinfo.gamename = our_movie.gamename;
248 pinfo.authors = our_movie.authors;
249 pinfo.movie_sram = our_movie.movie_sram;
250 pinfo.anchor_savestate = our_movie.anchor_savestate;
251 pinfo.movie_rtc_second = our_movie.movie_rtc_second;
252 pinfo.movie_rtc_subsecond = our_movie.movie_rtc_subsecond;
253 pinfo.projectid = our_movie.projectid;
254 project_copy_watches(pinfo);
255 project_copy_macros(pinfo, controls);
256 for(unsigned i = 0; i < ROM_SLOT_COUNT; i++) {
257 pinfo.roms[i] = our_rom.romimg[i].filename;
258 pinfo.romimg_sha256[i] = our_movie.romimg_sha256[i];
259 pinfo.romxml_sha256[i] = our_movie.romxml_sha256[i];
260 pinfo.namehint[i] = our_movie.namehint[i];
262 for(unsigned i = 0; i < luascripts->GetCount(); i++)
263 pinfo.luascripts.push_back(tostdstring(luascripts->GetString(i)));
264 if(memwatch->GetValue().length() == 0)
265 goto no_watch;
266 try {
267 std::istream& in = open_file_relative(tostdstring(memwatch->GetValue()), "");
268 while(in) {
269 std::string wname;
270 std::string wexpr;
271 std::getline(in, wname);
272 std::getline(in, wexpr);
273 pinfo.watches[strip_CR(wname)] = strip_CR(wexpr);
275 delete &in;
276 } catch(std::exception& e) {
277 show_message_ok(this, "Error", std::string("Can't load memory watch: ") + e.what(),
278 wxICON_EXCLAMATION);
279 return;
281 no_watch:
282 project_info* pinfo2 = new project_info(pinfo);
283 project_flush(pinfo2);
284 project_info* old_proj = project_get();
285 project_set(pinfo2, true);
286 if(old_proj)
287 delete old_proj;
288 EndModal(wxID_OK);
291 void wxwin_newproject::on_cancel(wxCommandEvent& e)
293 EndModal(wxID_CANCEL);
296 void wxwin_newproject::on_memorywatch_select(wxCommandEvent& e)
298 try {
299 std::string lwch = choose_file_load(this, "Select memory watch file", ".", filetype_watch);
300 try {
301 auto& p = open_file_relative(lwch, "");
302 delete &p;
303 } catch(std::exception& e) {
304 show_message_ok(this, "File not found", "File '" + lwch + "' can't be opened",
305 wxICON_EXCLAMATION);
306 return;
308 memwatch->SetValue(towxstring(lwch));
309 } catch(...) {
313 void wxwin_newproject::on_projname_edit(wxCommandEvent& e)
315 bool ok = true;
316 ok = ok && (projname->GetValue().length() > 0);
317 ok = ok && (projdir->GetValue().length() > 0);
318 ok = ok && (projpfx->GetValue().length() > 0);
319 boost::filesystem::path p(tostdstring(projdir->GetValue()));
320 ok = ok && boost::filesystem::is_directory(p);
321 okbutton->Enable(ok);
324 void wxwin_newproject::on_add(wxCommandEvent& e)
326 try {
327 std::string luascript = choose_file_load(this, "Pick lua script", ".", filetype_lua_script);
328 try {
329 auto& p = open_file_relative(luascript, "");
330 delete &p;
331 } catch(std::exception& e) {
332 show_message_ok(this, "File not found", "File '" + luascript + "' can't be opened",
333 wxICON_EXCLAMATION);
334 return;
336 luascripts->Append(towxstring(luascript));
337 } catch(...) {
341 void wxwin_newproject::on_remove(wxCommandEvent& e)
343 int sel = luascripts->GetSelection();
344 int count = luascripts->GetCount();
345 luascripts->Delete(sel);
346 if(sel < count - 1)
347 luascripts->SetSelection(sel);
348 else if(count > 1)
349 luascripts->SetSelection(count - 2);
350 else
351 luascripts->SetSelection(wxNOT_FOUND);
352 on_luasel(e);
355 void wxwin_newproject::reorder_scripts(int delta)
357 int sel = luascripts->GetSelection();
358 int count = luascripts->GetCount();
359 if(sel == wxNOT_FOUND || sel + delta >= count || sel + delta < 0)
360 return;
361 wxString a = luascripts->GetString(sel);
362 wxString b = luascripts->GetString(sel + delta);
363 luascripts->SetString(sel, b);
364 luascripts->SetString(sel + delta, a);
365 luascripts->SetSelection(sel + delta);
368 void wxwin_newproject::on_up(wxCommandEvent& e)
370 reorder_scripts(-1);
371 on_luasel(e);
374 void wxwin_newproject::on_down(wxCommandEvent& e)
376 reorder_scripts(1);
377 on_luasel(e);
380 void wxwin_newproject::on_luasel(wxCommandEvent& e)
382 int sel = luascripts->GetSelection();
383 int count = luascripts->GetCount();
384 removebutton->Enable(sel != wxNOT_FOUND);
385 upbutton->Enable(sel != wxNOT_FOUND && sel > 0);
386 downbutton->Enable(sel != wxNOT_FOUND && sel < count - 1);
389 void wxwin_newproject::on_directory_select(wxCommandEvent& e)
391 wxDirDialog* d = new wxDirDialog(this, wxT("Select project directory"), projdir->GetValue(),
392 wxDD_DIR_MUST_EXIST);
393 if(d->ShowModal() == wxID_CANCEL) {
394 d->Destroy();
395 return;
397 projdir->SetValue(d->GetPath());
398 d->Destroy();
402 class wxwin_project : public wxDialog
404 public:
405 wxwin_project();
406 ~wxwin_project();
407 void on_file_select(wxCommandEvent& e);
408 void on_new_select(wxCommandEvent& e);
409 void on_filename_change(wxCommandEvent& e);
410 void on_ask_filename(wxCommandEvent& e);
411 void on_quit(wxCommandEvent& e);
412 void on_load(wxCommandEvent& e);
413 private:
414 struct moviefile make_movie();
415 std::map<std::string, wxTextCtrl*> sram_files;
416 std::map<std::string, wxButton*> sram_choosers;
417 std::map<std::string, setting_select> settings;
418 wxTextCtrl* projectname;
419 wxTextCtrl* prefix;
420 wxTextCtrl* rtc_sec;
421 wxTextCtrl* rtc_subsec;
422 wxTextCtrl* authors;
423 wxButton* load;
424 wxButton* quit;
425 std::map<unsigned, std::string> sram_names;
430 void show_projectwindow(wxWindow* modwin)
432 if(!our_rom.rtype) {
433 show_message_ok(modwin, "Can't start new movie", "No ROM loaded", wxICON_EXCLAMATION);
434 return;
436 wxwin_project* projwin = new wxwin_project();
437 projwin->ShowModal();
438 projwin->Destroy();
441 //------------------------------------------------------------
443 wxwin_project::wxwin_project()
444 : wxDialog(NULL, wxID_ANY, wxT("Project settings"), wxDefaultPosition, wxSize(-1, -1),
445 wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX)
447 std::vector<wxString> cchoices;
449 std::set<std::string> sram_set = our_rom.rtype->srams();
451 Centre();
452 //2 Top-level block.
453 //- Notebook
454 //- Button bar.
455 wxBoxSizer* toplevel = new wxBoxSizer(wxVERTICAL);
456 SetSizer(toplevel);
457 wxPanel* new_panel = new wxPanel(this);
459 //The new page.
460 //3 Page-level blocks.
461 //- Controllertypes/initRTC/Gamename/SRAMs.
462 //- Authors explanation.
463 //- Authors
464 wxFlexGridSizer* new_sizer = new wxFlexGridSizer(3, 1, 0, 0);
465 new_panel->SetSizer(new_sizer);
466 //Controllertypes/Gamename/initRTC/SRAMs.
467 wxFlexGridSizer* mainblock = new wxFlexGridSizer(4 + our_rom.rtype->get_settings().settings.size() +
468 sram_set.size(), 2, 0, 0);
469 for(auto i : our_rom.rtype->get_settings().settings) {
470 settings.insert(std::make_pair(i.second.iname, setting_select(new_panel, i.second)));
471 mainblock->Add(settings.find(i.second.iname)->second.get_label());
472 mainblock->Add(settings.find(i.second.iname)->second.get_control());
474 mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Initial RTC value:")), 0, wxGROW);
475 wxFlexGridSizer* initrtc = new wxFlexGridSizer(1, 3, 0, 0);
476 initrtc->Add(rtc_sec = new wxTextCtrl(new_panel, wxID_ANY, wxT("1000000000"), wxDefaultPosition,
477 wxSize(150, -1)), 1, wxGROW);
478 initrtc->Add(new wxStaticText(new_panel, wxID_ANY, wxT(":")), 0, wxGROW);
479 initrtc->Add(rtc_subsec = new wxTextCtrl(new_panel, wxID_ANY, wxT("0"), wxDefaultPosition,
480 wxSize(150, -1)), 1, wxGROW);
481 mainblock->Add(initrtc, 0, wxGROW);
482 mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Game name:")), 0, wxGROW);
483 mainblock->Add(projectname = new wxTextCtrl(new_panel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)),
484 1, wxGROW);
485 mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Save prefix:")), 0, wxGROW);
486 mainblock->Add(prefix = new wxTextCtrl(new_panel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)), 1,
487 wxGROW);
488 unsigned idx = 0;
489 sram_set.insert("");
490 for(auto i : sram_set) {
491 std::string name = "SRAM " + i;
492 if(i == "")
493 name = "Anchor savestate";
494 mainblock->Add(new wxStaticText(new_panel, wxID_ANY, towxstring(name)), 0, wxGROW);
495 wxFlexGridSizer* fileblock2 = new wxFlexGridSizer(1, 2, 0, 0);
496 fileblock2->Add(sram_files[i] = new wxTextCtrl(new_panel, wxID_ANY, wxT(""), wxDefaultPosition,
497 wxSize(500, -1)), 1, wxGROW);
498 sram_files[i]->SetDropTarget(new textboxloadfilename(sram_files[i]));
499 fileblock2->Add(sram_choosers[i] = new wxButton(new_panel, ASK_SRAMS_BASE + idx, wxT("Pick")), 0,
500 wxGROW);
501 sram_files[i]->Connect(wxEVT_COMMAND_TEXT_UPDATED,
502 wxCommandEventHandler(wxwin_project::on_filename_change), NULL, this);
503 sram_files[i]->SetDropTarget(new textboxloadfilename(sram_files[i]));
504 sram_choosers[i]->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
505 wxCommandEventHandler(wxwin_project::on_ask_filename), NULL, this);
506 mainblock->Add(fileblock2, 0, wxGROW);
507 sram_names[idx] = i;
508 idx++;
510 new_sizer->Add(mainblock, 0, wxGROW);
512 //Authors
513 new_sizer->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Authors (one per line):")), 0, wxGROW);
514 new_sizer->Add(authors = new wxTextCtrl(new_panel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize,
515 wxTE_MULTILINE), 0, wxGROW);
516 authors->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wxwin_project::on_filename_change), NULL,
517 this);
519 toplevel->Add(new_panel, 1, wxGROW);
521 //Button bar.
522 wxBoxSizer* buttonbar = new wxBoxSizer(wxHORIZONTAL);
523 buttonbar->Add(load = new wxButton(this, wxID_ANY, wxT("Load")), 0, wxGROW);
524 buttonbar->AddStretchSpacer();
525 buttonbar->Add(quit = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
526 load->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
527 wxCommandEventHandler(wxwin_project::on_load), NULL, this);
528 quit->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
529 wxCommandEventHandler(wxwin_project::on_quit), NULL, this);
530 toplevel->Add(buttonbar, 0, wxGROW);
532 //This gets re-enabled later if needed.
533 load->Disable();
534 wxCommandEvent e2;
535 on_filename_change(e2);
537 mainblock->SetSizeHints(this);
538 new_sizer->SetSizeHints(this);
539 toplevel->SetSizeHints(this);
540 Fit();
543 wxwin_project::~wxwin_project()
547 void wxwin_project::on_ask_filename(wxCommandEvent& e)
549 int id = e.GetId();
550 try {
551 if(id >= ASK_SRAMS_BASE && id <= ASK_SRAMS_LAST) {
552 std::string fname = pick_file_member(this, "Choose " + sram_names[id - ASK_SRAMS_BASE], ".");
553 sram_files[sram_names[id - ASK_SRAMS_BASE]]->SetValue(towxstring(fname));
555 on_filename_change(e);
556 } catch(canceled_exception& e) {
560 void wxwin_project::on_filename_change(wxCommandEvent& e)
562 try {
563 boost::lexical_cast<int64_t>(tostdstring(rtc_sec->GetValue()));
564 if(boost::lexical_cast<int64_t>(tostdstring(rtc_subsec->GetValue())) < 0)
565 throw 42;
566 size_t lines = authors->GetNumberOfLines();
567 for(size_t i = 0; i < lines; i++) {
568 std::string l = tostdstring(authors->GetLineText(i));
569 if(l == "|")
570 throw 43;
572 load->Enable();
573 } catch(...) {
574 load->Disable();
578 void wxwin_project::on_quit(wxCommandEvent& e)
580 EndModal(0);
583 void wxwin_project::on_load(wxCommandEvent& e)
585 try {
586 moviefile mov = make_movie();
587 mov.start_paused = false;
588 mov.save("$MEMORY:wxwidgets-romload-tmp", 0, true);
589 platform::queue("load-state $MEMORY:wxwidgets-romload-tmp");
590 EndModal(0);
591 } catch(std::exception& e) {
592 show_message_ok(this, "Error loading movie", e.what(), wxICON_EXCLAMATION);
593 return;
597 struct moviefile wxwin_project::make_movie()
599 moviefile f;
600 f.force_corrupt = false;
601 f.gametype = &our_rom.rtype->combine_region(*our_rom.region);
602 for(auto i : settings) {
603 f.settings[i.first] = i.second.read();
604 if(!i.second.get_setting().validate(f.settings[i.first]))
605 throw std::runtime_error((stringfmt() << "Bad value for setting " << i.first).str());
607 f.coreversion = our_rom.rtype->get_core_identifier();
608 f.gamename = tostdstring(projectname->GetValue());
609 f.projectid = get_random_hexstring(40);
610 set_mprefix_for_project(f.projectid, tostdstring(prefix->GetValue()));
611 f.rerecords = "0";
612 for(size_t i = 0; i < ROM_SLOT_COUNT; i++) {
613 f.romimg_sha256[i] = our_rom.romimg[i].sha_256.read();
614 f.romxml_sha256[i] = our_rom.romxml[i].sha_256.read();
615 f.namehint[i] = our_rom.romimg[i].namehint;
617 size_t lines = authors->GetNumberOfLines();
618 for(size_t i = 0; i < lines; i++) {
619 std::string l = tostdstring(authors->GetLineText(i));
620 if(l != "" && l != "|")
621 f.authors.push_back(split_author(l));
623 for(auto i : sram_files) {
624 std::string sf = tostdstring(i.second->GetValue());
625 if(i.first != "") {
626 if(sf != "")
627 f.movie_sram[i.first] = read_file_relative(sf, "");
628 } else {
629 if(sf != "")
630 f.anchor_savestate = read_file_relative(sf, "");
633 f.is_savestate = false;
634 f.movie_rtc_second = f.rtc_second = boost::lexical_cast<int64_t>(tostdstring(rtc_sec->GetValue()));
635 f.movie_rtc_subsecond = f.rtc_subsecond = boost::lexical_cast<int64_t>(tostdstring(rtc_subsec->GetValue()));
636 if(f.movie_rtc_subsecond < 0)
637 throw std::runtime_error("RTC subsecond must be positive");
638 auto ctrldata = our_rom.rtype->controllerconfig(f.settings);
639 port_type_set& ports = port_type_set::make(ctrldata.ports, ctrldata.portindex());
640 f.input.clear(ports);
641 return f;
644 void open_new_project_window(wxWindow* parent)
646 if(our_rom.rtype->isnull()) {
647 show_message_ok(parent, "Can't start new project", "No ROM loaded", wxICON_EXCLAMATION);
648 return;
650 wxwin_newproject* projwin = new wxwin_newproject(parent);
651 projwin->ShowModal();
652 projwin->Destroy();