1 //Gaah... wx/wx.h (contains something that breaks if included after snes/snes.hpp from bsnes v085.
4 #include <wx/statbox.h>
5 #include <wx/notebook.h>
9 #include "core/controller.hpp"
10 #include "core/instance.hpp"
11 #include "core/moviedata.hpp"
12 #include "core/moviedata.hpp"
13 #include "core/framerate.hpp"
14 #include "core/project.hpp"
15 #include "core/random.hpp"
16 #include "core/rom.hpp"
17 #include "core/settings.hpp"
18 #include "core/window.hpp"
19 #include "interface/romtype.hpp"
20 #include "interface/setting.hpp"
21 #include "library/directory.hpp"
22 #include "library/string.hpp"
23 #include "library/zip.hpp"
25 #include "platform/wxwidgets/platform.hpp"
26 #include "platform/wxwidgets/loadsave.hpp"
29 #define ASK_SRAMS_BASE (wxID_HIGHEST + 129)
30 #define ASK_SRAMS_LAST (wxID_HIGHEST + 255)
34 std::string
generate_project_id()
36 return (stringfmt() << time(NULL
) << "_" << get_random_hexstring(4)).str();
39 class textboxloadfilename
: public wxFileDropTarget
42 textboxloadfilename(wxTextCtrl
* _ctrl
)
47 bool OnDropFiles(wxCoord x
, wxCoord y
, const wxArrayString
& filenames
)
50 if(filenames
.Count() != 1)
52 ctrl
->SetValue(filenames
[0]);
61 setting_select(wxWindow
* parent
, const core_setting
& s
);
62 wxWindow
* get_label() { return label
; }
63 wxWindow
* get_control();
64 const core_setting
& get_setting() { return setting
; }
74 setting_select::setting_select(wxWindow
* parent
, const core_setting
& s
)
79 if(!setting
.is_boolean())
80 label
= new wxStaticText(parent
, wxID_ANY
, towxstring(setting
.hname
));
82 label
= new wxStaticText(parent
, wxID_ANY
, towxstring(""));
86 if(setting
.is_boolean()) {
87 check
= new wxCheckBox(parent
, wxID_ANY
, towxstring(setting
.hname
));
88 check
->SetValue(s
.dflt
!= "0");
89 } else if(setting
.is_freetext()) {
90 text
= new wxTextCtrl(parent
, wxID_ANY
, towxstring(setting
.dflt
), wxDefaultPosition
,
93 std::vector
<wxString
> _hvalues
;
94 std::string dflt
= "";
95 for(auto i
: setting
.values
) {
96 _hvalues
.push_back(towxstring(i
.hname
));
97 if(i
.iname
== setting
.dflt
)
100 combo
= new wxComboBox(parent
, wxID_ANY
, towxstring(dflt
), wxDefaultPosition
,
101 wxDefaultSize
, _hvalues
.size(), &_hvalues
[0], wxCB_READONLY
);
105 wxWindow
* setting_select::get_control()
107 if(text
) return text
;
108 if(check
) return check
;
109 if(combo
) return combo
;
113 std::string
setting_select::read()
116 if(text
) return tostdstring(text
->GetValue());
117 if(check
) return check
->GetValue() ? "1" : "0";
118 if(combo
) return setting
.hvalue_to_ivalue(tostdstring(combo
->GetValue()));
122 class wxwin_newproject
: public wxDialog
125 wxwin_newproject(wxWindow
* parent
, emulator_instance
& _inst
);
127 void on_ok(wxCommandEvent
& e
);
128 void on_cancel(wxCommandEvent
& e
);
129 void on_projname_edit(wxCommandEvent
& e
);
130 void on_memorywatch_select(wxCommandEvent
& e
);
131 void on_directory_select(wxCommandEvent
& e
);
132 void on_add(wxCommandEvent
& e
);
133 void on_remove(wxCommandEvent
& e
);
134 void on_up(wxCommandEvent
& e
);
135 void on_down(wxCommandEvent
& e
);
136 void on_luasel(wxCommandEvent
& e
);
138 void reorder_scripts(int delta
);
139 emulator_instance
& inst
;
140 wxTextCtrl
* projname
;
141 wxTextCtrl
* memwatch
;
144 wxListBox
* luascripts
;
148 wxButton
* removebutton
;
150 wxButton
* downbutton
;
155 wxwin_newproject::~wxwin_newproject()
159 wxwin_newproject::wxwin_newproject(wxWindow
* parent
, emulator_instance
& _inst
)
160 : wxDialog(parent
, wxID_ANY
, wxT("New Project"), wxDefaultPosition
, wxSize(-1, -1),
161 wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
), inst(_inst
)
165 wxBoxSizer
* toplevel
= new wxBoxSizer(wxVERTICAL
);
168 wxFlexGridSizer
* c_s
= new wxFlexGridSizer(1, 2, 0, 0);
169 c_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Project name:")), 0, wxGROW
);
170 c_s
->Add(projname
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
172 projname
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
173 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
176 wxFlexGridSizer
* c4_s
= new wxFlexGridSizer(1, 3, 0, 0);
177 c4_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Directory:")), 0, wxGROW
);
178 c4_s
->Add(projdir
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
180 projdir
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
181 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
182 c4_s
->Add(sdir
= new wxButton(this, wxID_ANY
, wxT("...")), 1, wxGROW
);
183 sdir
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
184 wxCommandEventHandler(wxwin_newproject::on_directory_select
), NULL
, this);
187 wxFlexGridSizer
* c5_s
= new wxFlexGridSizer(1, 2, 0, 0);
188 c5_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Prefix:")), 0, wxGROW
);
189 c5_s
->Add(projpfx
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
191 projpfx
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
192 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
195 wxFlexGridSizer
* c2_s
= new wxFlexGridSizer(1, 3, 0, 0);
196 c2_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Memory watch:")), 0, wxGROW
);
197 c2_s
->Add(memwatch
= new wxTextCtrl(this, wxID_ANY
, wxT(""),
198 wxDefaultPosition
, wxSize(350, -1)), 1, wxGROW
);
200 c2_s
->Add(swatch
= new wxButton(this, wxID_ANY
, wxT("...")), 1, wxGROW
);
201 swatch
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
202 wxCommandEventHandler(wxwin_newproject::on_memorywatch_select
), NULL
, this);
205 toplevel
->Add(new wxStaticText(this, wxID_ANY
, wxT("Autoload lua scripts:")), 0, wxGROW
);
206 toplevel
->Add(luascripts
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxSize(400, 100)), 1,
208 luascripts
->Connect(wxEVT_COMMAND_LISTBOX_SELECTED
,
209 wxCommandEventHandler(wxwin_newproject::on_luasel
), NULL
, this);
211 wxFlexGridSizer
* c3_s
= new wxFlexGridSizer(1, 4, 0, 0);
212 c3_s
->Add(addbutton
= new wxButton(this, wxID_ANY
, wxT("Add")), 1, wxGROW
);
213 addbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
214 wxCommandEventHandler(wxwin_newproject::on_add
), NULL
, this);
215 c3_s
->Add(removebutton
= new wxButton(this, wxID_ANY
, wxT("Remove")), 1, wxGROW
);
216 removebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
217 wxCommandEventHandler(wxwin_newproject::on_remove
), NULL
, this);
218 removebutton
->Disable();
219 c3_s
->Add(upbutton
= new wxButton(this, wxID_ANY
, wxT("Up")), 1, wxGROW
);
220 upbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
221 wxCommandEventHandler(wxwin_newproject::on_up
), NULL
, this);
223 c3_s
->Add(downbutton
= new wxButton(this, wxID_ANY
, wxT("Down")), 1, wxGROW
);
224 downbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
225 wxCommandEventHandler(wxwin_newproject::on_down
), NULL
, this);
226 downbutton
->Disable();
229 wxBoxSizer
* buttonbar
= new wxBoxSizer(wxHORIZONTAL
);
230 buttonbar
->Add(okbutton
= new wxButton(this, wxID_ANY
, wxT("OK")), 0, wxGROW
);
231 buttonbar
->AddStretchSpacer();
232 buttonbar
->Add(cancel
= new wxButton(this, wxID_CANCEL
, wxT("Cancel")), 0, wxGROW
);
233 okbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
234 wxCommandEventHandler(wxwin_newproject::on_ok
), NULL
, this);
235 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
236 wxCommandEventHandler(wxwin_newproject::on_cancel
), NULL
, this);
237 toplevel
->Add(buttonbar
, 0, wxGROW
);
238 //This gets re-enabled later if needed.
241 toplevel
->SetSizeHints(this);
245 void wxwin_newproject::on_ok(wxCommandEvent
& e
)
249 show_message_ok(this, "Error", "Can't start project without movie", wxICON_EXCLAMATION
);
252 project_info
pinfo(*inst
.dispatch
);
253 pinfo
.id
= generate_project_id();
254 pinfo
.name
= tostdstring(projname
->GetValue());
255 pinfo
.rom
= inst
.rom
->get_pack_filename();
256 pinfo
.last_save
= "";
257 pinfo
.directory
= tostdstring(projdir
->GetValue());
258 pinfo
.prefix
= tostdstring(projpfx
->GetValue());
259 auto& m
= inst
.mlogic
->get_mfile();
260 pinfo
.gametype
= m
.gametype
->get_name();
261 pinfo
.settings
= m
.settings
;
262 pinfo
.coreversion
= m
.coreversion
;
263 pinfo
.gamename
= m
.gamename
;
264 pinfo
.authors
= m
.authors
;
265 pinfo
.movie_sram
= m
.movie_sram
;
266 pinfo
.anchor_savestate
= m
.anchor_savestate
;
267 pinfo
.movie_rtc_second
= m
.movie_rtc_second
;
268 pinfo
.movie_rtc_subsecond
= m
.movie_rtc_subsecond
;
269 pinfo
.projectid
= m
.projectid
;
270 pinfo
.active_branch
= 0;
271 pinfo
.next_branch
= 0;
272 inst
.project
->copy_watches(pinfo
);
273 inst
.project
->copy_macros(pinfo
, *inst
.controls
);
274 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
275 pinfo
.roms
[i
] = inst
.rom
->get_rom(i
).filename
;
276 pinfo
.romimg_sha256
[i
] = m
.romimg_sha256
[i
];
277 pinfo
.romxml_sha256
[i
] = m
.romxml_sha256
[i
];
278 pinfo
.namehint
[i
] = m
.namehint
[i
];
280 for(unsigned i
= 0; i
< luascripts
->GetCount(); i
++)
281 pinfo
.luascripts
.push_back(tostdstring(luascripts
->GetString(i
)));
282 if(memwatch
->GetValue().length() == 0)
285 std::istream
& in
= zip::openrel(tostdstring(memwatch
->GetValue()), "");
289 std::getline(in
, wname
);
290 std::getline(in
, wexpr
);
291 pinfo
.watches
[strip_CR(wname
)] = strip_CR(wexpr
);
294 } catch(std::exception
& e
) {
295 show_message_ok(this, "Error", std::string("Can't load memory watch: ") + e
.what(),
300 project_info
* pinfo2
= new project_info(pinfo
);
302 project_info
* old_proj
= inst
.project
->get();
303 inst
.project
->set(pinfo2
, true);
309 void wxwin_newproject::on_cancel(wxCommandEvent
& e
)
312 EndModal(wxID_CANCEL
);
315 void wxwin_newproject::on_memorywatch_select(wxCommandEvent
& e
)
319 std::string lwch
= choose_file_load(this, "Select memory watch file", ".", filetype_watch
);
321 auto& p
= zip::openrel(lwch
, "");
323 } catch(std::exception
& e
) {
324 show_message_ok(this, "File not found", "File '" + lwch
+ "' can't be opened",
328 memwatch
->SetValue(towxstring(lwch
));
333 void wxwin_newproject::on_projname_edit(wxCommandEvent
& e
)
336 ok
= ok
&& (projname
->GetValue().length() > 0);
337 ok
= ok
&& (projdir
->GetValue().length() > 0);
338 ok
= ok
&& (projpfx
->GetValue().length() > 0);
339 ok
= ok
&& directory::is_directory(tostdstring(projdir
->GetValue()));
340 okbutton
->Enable(ok
);
343 void wxwin_newproject::on_add(wxCommandEvent
& e
)
347 std::string luascript
= choose_file_load(this, "Pick lua script", ".", filetype_lua_script
);
349 auto& p
= zip::openrel(luascript
, "");
351 } catch(std::exception
& e
) {
352 show_message_ok(this, "File not found", "File '" + luascript
+ "' can't be opened",
356 luascripts
->Append(towxstring(luascript
));
361 void wxwin_newproject::on_remove(wxCommandEvent
& e
)
364 int sel
= luascripts
->GetSelection();
365 int count
= luascripts
->GetCount();
366 luascripts
->Delete(sel
);
368 luascripts
->SetSelection(sel
);
370 luascripts
->SetSelection(count
- 2);
372 luascripts
->SetSelection(wxNOT_FOUND
);
376 void wxwin_newproject::reorder_scripts(int delta
)
379 int sel
= luascripts
->GetSelection();
380 int count
= luascripts
->GetCount();
381 if(sel
== wxNOT_FOUND
|| sel
+ delta
>= count
|| sel
+ delta
< 0)
383 wxString a
= luascripts
->GetString(sel
);
384 wxString b
= luascripts
->GetString(sel
+ delta
);
385 luascripts
->SetString(sel
, b
);
386 luascripts
->SetString(sel
+ delta
, a
);
387 luascripts
->SetSelection(sel
+ delta
);
390 void wxwin_newproject::on_up(wxCommandEvent
& e
)
397 void wxwin_newproject::on_down(wxCommandEvent
& e
)
404 void wxwin_newproject::on_luasel(wxCommandEvent
& e
)
407 int sel
= luascripts
->GetSelection();
408 int count
= luascripts
->GetCount();
409 removebutton
->Enable(sel
!= wxNOT_FOUND
);
410 upbutton
->Enable(sel
!= wxNOT_FOUND
&& sel
> 0);
411 downbutton
->Enable(sel
!= wxNOT_FOUND
&& sel
< count
- 1);
414 void wxwin_newproject::on_directory_select(wxCommandEvent
& e
)
417 wxDirDialog
* d
= new wxDirDialog(this, wxT("Select project directory"), projdir
->GetValue(),
418 wxDD_DIR_MUST_EXIST
);
419 if(d
->ShowModal() == wxID_CANCEL
) {
423 projdir
->SetValue(d
->GetPath());
427 int get_setting_class(const core_setting
& a
)
436 bool compare_settings(const std::pair
<std::string
, core_setting
*>& a
,
437 const std::pair
<std::string
, core_setting
*>& b
)
439 int aclass
= get_setting_class(*a
.second
);
440 int bclass
= get_setting_class(*b
.second
);
441 if(aclass
< bclass
) return true;
442 if(aclass
> bclass
) return false;
443 if(a
.second
->hname
< b
.second
->hname
) return true;
444 if(a
.second
->hname
> b
.second
->hname
) return false;
448 std::vector
<std::pair
<std::string
, core_setting
*>> sort_settingblock(std::map
<std::string
,
449 core_setting
>& block
)
451 std::vector
<std::pair
<std::string
, core_setting
*>> ret
;
453 ret
.push_back(std::make_pair(i
.first
, &i
.second
));
454 std::sort(ret
.begin(), ret
.end(), compare_settings
);
459 class wxwin_project
: public wxDialog
462 wxwin_project(emulator_instance
& _inst
);
464 void on_file_select(wxCommandEvent
& e
);
465 void on_new_select(wxCommandEvent
& e
);
466 void on_filename_change(wxCommandEvent
& e
);
467 void on_ask_filename(wxCommandEvent
& e
);
468 void on_quit(wxCommandEvent
& e
);
469 void on_load(wxCommandEvent
& e
);
471 struct moviefile
& make_movie();
472 emulator_instance
& inst
;
473 std::map
<std::string
, wxTextCtrl
*> sram_files
;
474 std::map
<std::string
, wxButton
*> sram_choosers
;
475 std::map
<std::string
, setting_select
> settings
;
476 wxTextCtrl
* projectname
;
479 wxTextCtrl
* rtc_subsec
;
483 std::map
<unsigned, std::string
> sram_names
;
488 void show_projectwindow(wxWindow
* modwin
, emulator_instance
& inst
)
491 if(inst
.rom
->isnull()) {
492 show_message_ok(modwin
, "Can't start new movie", "No ROM loaded", wxICON_EXCLAMATION
);
495 wxwin_project
* projwin
= new wxwin_project(inst
);
496 projwin
->ShowModal();
500 //------------------------------------------------------------
502 wxwin_project::wxwin_project(emulator_instance
& _inst
)
503 : wxDialog(NULL
, wxID_ANY
, wxT("Project settings"), wxDefaultPosition
, wxSize(-1, -1),
504 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
), inst(_inst
)
507 std::vector
<wxString
> cchoices
;
509 std::set
<std::string
> sram_set
= inst
.rom
->srams();
515 wxBoxSizer
* toplevel
= new wxBoxSizer(wxVERTICAL
);
517 wxPanel
* new_panel
= new wxPanel(this);
520 //3 Page-level blocks.
521 //- Controllertypes/initRTC/Gamename/SRAMs.
522 //- Authors explanation.
524 wxFlexGridSizer
* new_sizer
= new wxFlexGridSizer(3, 1, 0, 0);
525 new_panel
->SetSizer(new_sizer
);
526 //Controllertypes/Gamename/initRTC/SRAMs.
527 auto settingblock
= inst
.rom
->get_settings().settings
;
528 wxFlexGridSizer
* mainblock
= new wxFlexGridSizer(4 + settingblock
.size() + sram_set
.size(), 2, 0, 0);
529 auto _settingblock
= sort_settingblock(settingblock
);
530 for(auto i
: _settingblock
) {
531 settings
.insert(std::make_pair(i
.second
->iname
, setting_select(new_panel
, *i
.second
)));
532 mainblock
->Add(settings
.find(i
.second
->iname
)->second
.get_label());
533 mainblock
->Add(settings
.find(i
.second
->iname
)->second
.get_control());
535 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Initial RTC value:")), 0, wxGROW
);
536 wxFlexGridSizer
* initrtc
= new wxFlexGridSizer(1, 3, 0, 0);
537 initrtc
->Add(rtc_sec
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT("1000000000"), wxDefaultPosition
,
538 wxSize(150, -1)), 1, wxGROW
);
539 initrtc
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT(":")), 0, wxGROW
);
540 initrtc
->Add(rtc_subsec
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT("0"), wxDefaultPosition
,
541 wxSize(150, -1)), 1, wxGROW
);
542 mainblock
->Add(initrtc
, 0, wxGROW
);
543 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Game name:")), 0, wxGROW
);
544 mainblock
->Add(projectname
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)),
546 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Save prefix:")), 0, wxGROW
);
547 mainblock
->Add(prefix
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
551 for(auto i
: sram_set
) {
552 std::string name
= "SRAM " + i
;
554 name
= "Anchor savestate";
555 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, towxstring(name
)), 0, wxGROW
);
556 wxFlexGridSizer
* fileblock2
= new wxFlexGridSizer(1, 2, 0, 0);
557 fileblock2
->Add(sram_files
[i
] = new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
,
558 wxSize(500, -1)), 1, wxGROW
);
559 sram_files
[i
]->SetDropTarget(new textboxloadfilename(sram_files
[i
]));
560 fileblock2
->Add(sram_choosers
[i
] = new wxButton(new_panel
, ASK_SRAMS_BASE
+ idx
, wxT("Pick")), 0,
562 sram_files
[i
]->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
563 wxCommandEventHandler(wxwin_project::on_filename_change
), NULL
, this);
564 sram_files
[i
]->SetDropTarget(new textboxloadfilename(sram_files
[i
]));
565 sram_choosers
[i
]->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
566 wxCommandEventHandler(wxwin_project::on_ask_filename
), NULL
, this);
567 mainblock
->Add(fileblock2
, 0, wxGROW
);
571 new_sizer
->Add(mainblock
, 0, wxGROW
);
574 new_sizer
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Authors (one per line):")), 0, wxGROW
);
575 new_sizer
->Add(authors
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
576 wxTE_MULTILINE
), 0, wxGROW
);
577 authors
->Connect(wxEVT_COMMAND_TEXT_UPDATED
, wxCommandEventHandler(wxwin_project::on_filename_change
), NULL
,
580 toplevel
->Add(new_panel
, 1, wxGROW
);
583 wxBoxSizer
* buttonbar
= new wxBoxSizer(wxHORIZONTAL
);
584 buttonbar
->Add(load
= new wxButton(this, wxID_ANY
, wxT("Load")), 0, wxGROW
);
585 buttonbar
->AddStretchSpacer();
586 buttonbar
->Add(quit
= new wxButton(this, wxID_CANCEL
, wxT("Cancel")), 0, wxGROW
);
587 load
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
588 wxCommandEventHandler(wxwin_project::on_load
), NULL
, this);
589 quit
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
590 wxCommandEventHandler(wxwin_project::on_quit
), NULL
, this);
591 toplevel
->Add(buttonbar
, 0, wxGROW
);
593 //This gets re-enabled later if needed.
596 on_filename_change(e2
);
598 mainblock
->SetSizeHints(this);
599 new_sizer
->SetSizeHints(this);
600 toplevel
->SetSizeHints(this);
604 wxwin_project::~wxwin_project()
608 void wxwin_project::on_ask_filename(wxCommandEvent
& e
)
613 if(id
>= ASK_SRAMS_BASE
&& id
<= ASK_SRAMS_LAST
) {
614 std::string fname
= pick_file_member(this, "Choose " + sram_names
[id
- ASK_SRAMS_BASE
], ".");
615 sram_files
[sram_names
[id
- ASK_SRAMS_BASE
]]->SetValue(towxstring(fname
));
617 on_filename_change(e
);
618 } catch(canceled_exception
& e
) {
622 void wxwin_project::on_filename_change(wxCommandEvent
& e
)
626 raw_lexical_cast
<int64_t>(tostdstring(rtc_sec
->GetValue()));
627 if(raw_lexical_cast
<int64_t>(tostdstring(rtc_subsec
->GetValue())) < 0)
629 size_t lines
= authors
->GetNumberOfLines();
630 for(size_t i
= 0; i
< lines
; i
++) {
631 std::string l
= tostdstring(authors
->GetLineText(i
));
641 void wxwin_project::on_quit(wxCommandEvent
& e
)
646 void wxwin_project::on_load(wxCommandEvent
& e
)
650 moviefile
& mov
= make_movie();
651 mov
.start_paused
= false;
652 rrdata_set tmp_rdata
;
653 mov
.save("$MEMORY:wxwidgets-romload-tmp", 0, true, tmp_rdata
, false);
654 inst
.iqueue
->queue("load-state $MEMORY:wxwidgets-romload-tmp");
656 } catch(std::exception
& e
) {
657 show_message_ok(this, "Error loading movie", e
.what(), wxICON_EXCLAMATION
);
662 struct moviefile
& wxwin_project::make_movie()
665 moviefile
& f
= *new moviefile
;
666 f
.force_corrupt
= false;
667 f
.gametype
= &inst
.rom
->get_sysregion();
668 for(auto i
: settings
) {
669 f
.settings
[i
.first
] = i
.second
.read();
670 if(!i
.second
.get_setting().validate(f
.settings
[i
.first
]))
671 throw std::runtime_error((stringfmt() << "Bad value for setting " << i
.first
).str());
673 f
.coreversion
= inst
.rom
->get_core_identifier();
674 f
.gamename
= tostdstring(projectname
->GetValue());
675 f
.projectid
= get_random_hexstring(40);
676 set_mprefix_for_project(f
.projectid
, tostdstring(prefix
->GetValue()));
678 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
679 auto& img
= inst
.rom
->get_rom(i
);
680 auto& xml
= inst
.rom
->get_markup(i
);
681 f
.romimg_sha256
[i
] = img
.sha_256
.read();
682 f
.romxml_sha256
[i
] = xml
.sha_256
.read();
683 f
.namehint
[i
] = img
.namehint
;
685 size_t lines
= authors
->GetNumberOfLines();
686 for(size_t i
= 0; i
< lines
; i
++) {
687 std::string l
= tostdstring(authors
->GetLineText(i
));
688 if(l
!= "" && l
!= "|")
689 f
.authors
.push_back(split_author(l
));
691 for(auto i
: sram_files
) {
692 std::string sf
= tostdstring(i
.second
->GetValue());
693 std::vector
<char>* target
;
695 target
= &(f
.movie_sram
[i
.first
]);
697 target
= &(f
.anchor_savestate
);
700 if(moviefile::is_movie_or_savestate(sf
)) {
701 moviefile::sram_extractor
e(sf
);
702 e
.read(i
.first
, *target
);
704 *target
= zip::readrel(sf
, "");
707 f
.movie_rtc_second
= f
.dyn
.rtc_second
= raw_lexical_cast
<int64_t>(tostdstring(rtc_sec
->GetValue()));
708 f
.movie_rtc_subsecond
= f
.dyn
.rtc_subsecond
=
709 raw_lexical_cast
<int64_t>(tostdstring(rtc_subsec
->GetValue()));
710 if(f
.movie_rtc_subsecond
< 0)
711 throw std::runtime_error("RTC subsecond must be positive");
712 auto ctrldata
= inst
.rom
->controllerconfig(f
.settings
);
713 portctrl::type_set
& ports
= portctrl::type_set::make(ctrldata
.ports
, ctrldata
.portindex());
714 f
.create_default_branch(ports
);
718 void open_new_project_window(wxWindow
* parent
, emulator_instance
& inst
)
721 if(inst
.rom
->isnull()) {
722 show_message_ok(parent
, "Can't start new project", "No ROM loaded", wxICON_EXCLAMATION
);
725 wxwin_newproject
* projwin
= new wxwin_newproject(parent
, inst
);
726 projwin
->ShowModal();