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"
24 #include <boost/lexical_cast.hpp>
26 #include "platform/wxwidgets/platform.hpp"
27 #include "platform/wxwidgets/loadsave.hpp"
30 #define ASK_SRAMS_BASE (wxID_HIGHEST + 129)
31 #define ASK_SRAMS_LAST (wxID_HIGHEST + 255)
35 std::string
generate_project_id()
37 return (stringfmt() << time(NULL
) << "_" << get_random_hexstring(4)).str();
40 class textboxloadfilename
: public wxFileDropTarget
43 textboxloadfilename(wxTextCtrl
* _ctrl
)
48 bool OnDropFiles(wxCoord x
, wxCoord y
, const wxArrayString
& filenames
)
51 if(filenames
.Count() != 1)
53 ctrl
->SetValue(filenames
[0]);
62 setting_select(wxWindow
* parent
, const core_setting
& s
);
63 wxWindow
* get_label() { return label
; }
64 wxWindow
* get_control();
65 const core_setting
& get_setting() { return setting
; }
75 setting_select::setting_select(wxWindow
* parent
, const core_setting
& s
)
80 if(!setting
.is_boolean())
81 label
= new wxStaticText(parent
, wxID_ANY
, towxstring(setting
.hname
));
83 label
= new wxStaticText(parent
, wxID_ANY
, towxstring(""));
87 if(setting
.is_boolean()) {
88 check
= new wxCheckBox(parent
, wxID_ANY
, towxstring(setting
.hname
));
89 check
->SetValue(s
.dflt
!= "0");
90 } else if(setting
.is_freetext()) {
91 text
= new wxTextCtrl(parent
, wxID_ANY
, towxstring(setting
.dflt
), wxDefaultPosition
,
94 std::vector
<wxString
> _hvalues
;
95 std::string dflt
= "";
96 for(auto i
: setting
.values
) {
97 _hvalues
.push_back(towxstring(i
.hname
));
98 if(i
.iname
== setting
.dflt
)
101 combo
= new wxComboBox(parent
, wxID_ANY
, towxstring(dflt
), wxDefaultPosition
,
102 wxDefaultSize
, _hvalues
.size(), &_hvalues
[0], wxCB_READONLY
);
106 wxWindow
* setting_select::get_control()
108 if(text
) return text
;
109 if(check
) return check
;
110 if(combo
) return combo
;
114 std::string
setting_select::read()
117 if(text
) return tostdstring(text
->GetValue());
118 if(check
) return check
->GetValue() ? "1" : "0";
119 if(combo
) return setting
.hvalue_to_ivalue(tostdstring(combo
->GetValue()));
123 class wxwin_newproject
: public wxDialog
126 wxwin_newproject(wxWindow
* parent
, emulator_instance
& _inst
);
128 void on_ok(wxCommandEvent
& e
);
129 void on_cancel(wxCommandEvent
& e
);
130 void on_projname_edit(wxCommandEvent
& e
);
131 void on_memorywatch_select(wxCommandEvent
& e
);
132 void on_directory_select(wxCommandEvent
& e
);
133 void on_add(wxCommandEvent
& e
);
134 void on_remove(wxCommandEvent
& e
);
135 void on_up(wxCommandEvent
& e
);
136 void on_down(wxCommandEvent
& e
);
137 void on_luasel(wxCommandEvent
& e
);
139 void reorder_scripts(int delta
);
140 emulator_instance
& inst
;
141 wxTextCtrl
* projname
;
142 wxTextCtrl
* memwatch
;
145 wxListBox
* luascripts
;
149 wxButton
* removebutton
;
151 wxButton
* downbutton
;
156 wxwin_newproject::~wxwin_newproject()
160 wxwin_newproject::wxwin_newproject(wxWindow
* parent
, emulator_instance
& _inst
)
161 : wxDialog(parent
, wxID_ANY
, wxT("New Project"), wxDefaultPosition
, wxSize(-1, -1),
162 wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
), inst(_inst
)
166 wxBoxSizer
* toplevel
= new wxBoxSizer(wxVERTICAL
);
169 wxFlexGridSizer
* c_s
= new wxFlexGridSizer(1, 2, 0, 0);
170 c_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Project name:")), 0, wxGROW
);
171 c_s
->Add(projname
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
173 projname
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
174 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
177 wxFlexGridSizer
* c4_s
= new wxFlexGridSizer(1, 3, 0, 0);
178 c4_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Directory:")), 0, wxGROW
);
179 c4_s
->Add(projdir
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
181 projdir
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
182 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
183 c4_s
->Add(sdir
= new wxButton(this, wxID_ANY
, wxT("...")), 1, wxGROW
);
184 sdir
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
185 wxCommandEventHandler(wxwin_newproject::on_directory_select
), NULL
, this);
188 wxFlexGridSizer
* c5_s
= new wxFlexGridSizer(1, 2, 0, 0);
189 c5_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Prefix:")), 0, wxGROW
);
190 c5_s
->Add(projpfx
= new wxTextCtrl(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
192 projpfx
->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
193 wxCommandEventHandler(wxwin_newproject::on_projname_edit
), NULL
, this);
196 wxFlexGridSizer
* c2_s
= new wxFlexGridSizer(1, 3, 0, 0);
197 c2_s
->Add(new wxStaticText(this, wxID_ANY
, wxT("Memory watch:")), 0, wxGROW
);
198 c2_s
->Add(memwatch
= new wxTextCtrl(this, wxID_ANY
, wxT(""),
199 wxDefaultPosition
, wxSize(350, -1)), 1, wxGROW
);
201 c2_s
->Add(swatch
= new wxButton(this, wxID_ANY
, wxT("...")), 1, wxGROW
);
202 swatch
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
203 wxCommandEventHandler(wxwin_newproject::on_memorywatch_select
), NULL
, this);
206 toplevel
->Add(new wxStaticText(this, wxID_ANY
, wxT("Autoload lua scripts:")), 0, wxGROW
);
207 toplevel
->Add(luascripts
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxSize(400, 100)), 1,
209 luascripts
->Connect(wxEVT_COMMAND_LISTBOX_SELECTED
,
210 wxCommandEventHandler(wxwin_newproject::on_luasel
), NULL
, this);
212 wxFlexGridSizer
* c3_s
= new wxFlexGridSizer(1, 4, 0, 0);
213 c3_s
->Add(addbutton
= new wxButton(this, wxID_ANY
, wxT("Add")), 1, wxGROW
);
214 addbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
215 wxCommandEventHandler(wxwin_newproject::on_add
), NULL
, this);
216 c3_s
->Add(removebutton
= new wxButton(this, wxID_ANY
, wxT("Remove")), 1, wxGROW
);
217 removebutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
218 wxCommandEventHandler(wxwin_newproject::on_remove
), NULL
, this);
219 removebutton
->Disable();
220 c3_s
->Add(upbutton
= new wxButton(this, wxID_ANY
, wxT("Up")), 1, wxGROW
);
221 upbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
222 wxCommandEventHandler(wxwin_newproject::on_up
), NULL
, this);
224 c3_s
->Add(downbutton
= new wxButton(this, wxID_ANY
, wxT("Down")), 1, wxGROW
);
225 downbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
226 wxCommandEventHandler(wxwin_newproject::on_down
), NULL
, this);
227 downbutton
->Disable();
230 wxBoxSizer
* buttonbar
= new wxBoxSizer(wxHORIZONTAL
);
231 buttonbar
->Add(okbutton
= new wxButton(this, wxID_ANY
, wxT("OK")), 0, wxGROW
);
232 buttonbar
->AddStretchSpacer();
233 buttonbar
->Add(cancel
= new wxButton(this, wxID_CANCEL
, wxT("Cancel")), 0, wxGROW
);
234 okbutton
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
235 wxCommandEventHandler(wxwin_newproject::on_ok
), NULL
, this);
236 cancel
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
237 wxCommandEventHandler(wxwin_newproject::on_cancel
), NULL
, this);
238 toplevel
->Add(buttonbar
, 0, wxGROW
);
239 //This gets re-enabled later if needed.
242 toplevel
->SetSizeHints(this);
246 void wxwin_newproject::on_ok(wxCommandEvent
& e
)
250 show_message_ok(this, "Error", "Can't start project without movie", wxICON_EXCLAMATION
);
253 project_info
pinfo(*inst
.dispatch
);
254 pinfo
.id
= generate_project_id();
255 pinfo
.name
= tostdstring(projname
->GetValue());
256 pinfo
.rom
= inst
.rom
->load_filename
;
257 pinfo
.last_save
= "";
258 pinfo
.directory
= tostdstring(projdir
->GetValue());
259 pinfo
.prefix
= tostdstring(projpfx
->GetValue());
260 auto& m
= inst
.mlogic
->get_mfile();
261 pinfo
.gametype
= m
.gametype
->get_name();
262 pinfo
.settings
= m
.settings
;
263 pinfo
.coreversion
= m
.coreversion
;
264 pinfo
.gamename
= m
.gamename
;
265 pinfo
.authors
= m
.authors
;
266 pinfo
.movie_sram
= m
.movie_sram
;
267 pinfo
.anchor_savestate
= m
.anchor_savestate
;
268 pinfo
.movie_rtc_second
= m
.movie_rtc_second
;
269 pinfo
.movie_rtc_subsecond
= m
.movie_rtc_subsecond
;
270 pinfo
.projectid
= m
.projectid
;
271 pinfo
.active_branch
= 0;
272 pinfo
.next_branch
= 0;
273 inst
.project
->copy_watches(pinfo
);
274 inst
.project
->copy_macros(pinfo
, *inst
.controls
);
275 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
276 pinfo
.roms
[i
] = inst
.rom
->romimg
[i
].filename
;
277 pinfo
.romimg_sha256
[i
] = m
.romimg_sha256
[i
];
278 pinfo
.romxml_sha256
[i
] = m
.romxml_sha256
[i
];
279 pinfo
.namehint
[i
] = m
.namehint
[i
];
281 for(unsigned i
= 0; i
< luascripts
->GetCount(); i
++)
282 pinfo
.luascripts
.push_back(tostdstring(luascripts
->GetString(i
)));
283 if(memwatch
->GetValue().length() == 0)
286 std::istream
& in
= zip::openrel(tostdstring(memwatch
->GetValue()), "");
290 std::getline(in
, wname
);
291 std::getline(in
, wexpr
);
292 pinfo
.watches
[strip_CR(wname
)] = strip_CR(wexpr
);
295 } catch(std::exception
& e
) {
296 show_message_ok(this, "Error", std::string("Can't load memory watch: ") + e
.what(),
301 project_info
* pinfo2
= new project_info(pinfo
);
303 project_info
* old_proj
= inst
.project
->get();
304 inst
.project
->set(pinfo2
, true);
310 void wxwin_newproject::on_cancel(wxCommandEvent
& e
)
313 EndModal(wxID_CANCEL
);
316 void wxwin_newproject::on_memorywatch_select(wxCommandEvent
& e
)
320 std::string lwch
= choose_file_load(this, "Select memory watch file", ".", filetype_watch
);
322 auto& p
= zip::openrel(lwch
, "");
324 } catch(std::exception
& e
) {
325 show_message_ok(this, "File not found", "File '" + lwch
+ "' can't be opened",
329 memwatch
->SetValue(towxstring(lwch
));
334 void wxwin_newproject::on_projname_edit(wxCommandEvent
& e
)
337 ok
= ok
&& (projname
->GetValue().length() > 0);
338 ok
= ok
&& (projdir
->GetValue().length() > 0);
339 ok
= ok
&& (projpfx
->GetValue().length() > 0);
340 ok
= ok
&& directory::is_directory(tostdstring(projdir
->GetValue()));
341 okbutton
->Enable(ok
);
344 void wxwin_newproject::on_add(wxCommandEvent
& e
)
348 std::string luascript
= choose_file_load(this, "Pick lua script", ".", filetype_lua_script
);
350 auto& p
= zip::openrel(luascript
, "");
352 } catch(std::exception
& e
) {
353 show_message_ok(this, "File not found", "File '" + luascript
+ "' can't be opened",
357 luascripts
->Append(towxstring(luascript
));
362 void wxwin_newproject::on_remove(wxCommandEvent
& e
)
365 int sel
= luascripts
->GetSelection();
366 int count
= luascripts
->GetCount();
367 luascripts
->Delete(sel
);
369 luascripts
->SetSelection(sel
);
371 luascripts
->SetSelection(count
- 2);
373 luascripts
->SetSelection(wxNOT_FOUND
);
377 void wxwin_newproject::reorder_scripts(int delta
)
380 int sel
= luascripts
->GetSelection();
381 int count
= luascripts
->GetCount();
382 if(sel
== wxNOT_FOUND
|| sel
+ delta
>= count
|| sel
+ delta
< 0)
384 wxString a
= luascripts
->GetString(sel
);
385 wxString b
= luascripts
->GetString(sel
+ delta
);
386 luascripts
->SetString(sel
, b
);
387 luascripts
->SetString(sel
+ delta
, a
);
388 luascripts
->SetSelection(sel
+ delta
);
391 void wxwin_newproject::on_up(wxCommandEvent
& e
)
398 void wxwin_newproject::on_down(wxCommandEvent
& e
)
405 void wxwin_newproject::on_luasel(wxCommandEvent
& e
)
408 int sel
= luascripts
->GetSelection();
409 int count
= luascripts
->GetCount();
410 removebutton
->Enable(sel
!= wxNOT_FOUND
);
411 upbutton
->Enable(sel
!= wxNOT_FOUND
&& sel
> 0);
412 downbutton
->Enable(sel
!= wxNOT_FOUND
&& sel
< count
- 1);
415 void wxwin_newproject::on_directory_select(wxCommandEvent
& e
)
418 wxDirDialog
* d
= new wxDirDialog(this, wxT("Select project directory"), projdir
->GetValue(),
419 wxDD_DIR_MUST_EXIST
);
420 if(d
->ShowModal() == wxID_CANCEL
) {
424 projdir
->SetValue(d
->GetPath());
428 int get_setting_class(const core_setting
& a
)
437 bool compare_settings(const std::pair
<std::string
, core_setting
*>& a
,
438 const std::pair
<std::string
, core_setting
*>& b
)
440 int aclass
= get_setting_class(*a
.second
);
441 int bclass
= get_setting_class(*b
.second
);
442 if(aclass
< bclass
) return true;
443 if(aclass
> bclass
) return false;
444 if(a
.second
->hname
< b
.second
->hname
) return true;
445 if(a
.second
->hname
> b
.second
->hname
) return false;
449 std::vector
<std::pair
<std::string
, core_setting
*>> sort_settingblock(std::map
<std::string
,
450 core_setting
>& block
)
452 std::vector
<std::pair
<std::string
, core_setting
*>> ret
;
454 ret
.push_back(std::make_pair(i
.first
, &i
.second
));
455 std::sort(ret
.begin(), ret
.end(), compare_settings
);
460 class wxwin_project
: public wxDialog
463 wxwin_project(emulator_instance
& _inst
);
465 void on_file_select(wxCommandEvent
& e
);
466 void on_new_select(wxCommandEvent
& e
);
467 void on_filename_change(wxCommandEvent
& e
);
468 void on_ask_filename(wxCommandEvent
& e
);
469 void on_quit(wxCommandEvent
& e
);
470 void on_load(wxCommandEvent
& e
);
472 struct moviefile
& make_movie();
473 emulator_instance
& inst
;
474 std::map
<std::string
, wxTextCtrl
*> sram_files
;
475 std::map
<std::string
, wxButton
*> sram_choosers
;
476 std::map
<std::string
, setting_select
> settings
;
477 wxTextCtrl
* projectname
;
480 wxTextCtrl
* rtc_subsec
;
484 std::map
<unsigned, std::string
> sram_names
;
489 void show_projectwindow(wxWindow
* modwin
, emulator_instance
& inst
)
492 if(inst
.rom
->isnull()) {
493 show_message_ok(modwin
, "Can't start new movie", "No ROM loaded", wxICON_EXCLAMATION
);
496 wxwin_project
* projwin
= new wxwin_project(inst
);
497 projwin
->ShowModal();
501 //------------------------------------------------------------
503 wxwin_project::wxwin_project(emulator_instance
& _inst
)
504 : wxDialog(NULL
, wxID_ANY
, wxT("Project settings"), wxDefaultPosition
, wxSize(-1, -1),
505 wxMINIMIZE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
| wxCLOSE_BOX
), inst(_inst
)
508 std::vector
<wxString
> cchoices
;
510 std::set
<std::string
> sram_set
= inst
.rom
->srams();
516 wxBoxSizer
* toplevel
= new wxBoxSizer(wxVERTICAL
);
518 wxPanel
* new_panel
= new wxPanel(this);
521 //3 Page-level blocks.
522 //- Controllertypes/initRTC/Gamename/SRAMs.
523 //- Authors explanation.
525 wxFlexGridSizer
* new_sizer
= new wxFlexGridSizer(3, 1, 0, 0);
526 new_panel
->SetSizer(new_sizer
);
527 //Controllertypes/Gamename/initRTC/SRAMs.
528 auto settingblock
= inst
.rom
->get_settings().settings
;
529 wxFlexGridSizer
* mainblock
= new wxFlexGridSizer(4 + settingblock
.size() + sram_set
.size(), 2, 0, 0);
530 auto _settingblock
= sort_settingblock(settingblock
);
531 for(auto i
: _settingblock
) {
532 settings
.insert(std::make_pair(i
.second
->iname
, setting_select(new_panel
, *i
.second
)));
533 mainblock
->Add(settings
.find(i
.second
->iname
)->second
.get_label());
534 mainblock
->Add(settings
.find(i
.second
->iname
)->second
.get_control());
536 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Initial RTC value:")), 0, wxGROW
);
537 wxFlexGridSizer
* initrtc
= new wxFlexGridSizer(1, 3, 0, 0);
538 initrtc
->Add(rtc_sec
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT("1000000000"), wxDefaultPosition
,
539 wxSize(150, -1)), 1, wxGROW
);
540 initrtc
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT(":")), 0, wxGROW
);
541 initrtc
->Add(rtc_subsec
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT("0"), wxDefaultPosition
,
542 wxSize(150, -1)), 1, wxGROW
);
543 mainblock
->Add(initrtc
, 0, wxGROW
);
544 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Game name:")), 0, wxGROW
);
545 mainblock
->Add(projectname
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)),
547 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Save prefix:")), 0, wxGROW
);
548 mainblock
->Add(prefix
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxSize(400, -1)), 1,
552 for(auto i
: sram_set
) {
553 std::string name
= "SRAM " + i
;
555 name
= "Anchor savestate";
556 mainblock
->Add(new wxStaticText(new_panel
, wxID_ANY
, towxstring(name
)), 0, wxGROW
);
557 wxFlexGridSizer
* fileblock2
= new wxFlexGridSizer(1, 2, 0, 0);
558 fileblock2
->Add(sram_files
[i
] = new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
,
559 wxSize(500, -1)), 1, wxGROW
);
560 sram_files
[i
]->SetDropTarget(new textboxloadfilename(sram_files
[i
]));
561 fileblock2
->Add(sram_choosers
[i
] = new wxButton(new_panel
, ASK_SRAMS_BASE
+ idx
, wxT("Pick")), 0,
563 sram_files
[i
]->Connect(wxEVT_COMMAND_TEXT_UPDATED
,
564 wxCommandEventHandler(wxwin_project::on_filename_change
), NULL
, this);
565 sram_files
[i
]->SetDropTarget(new textboxloadfilename(sram_files
[i
]));
566 sram_choosers
[i
]->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
567 wxCommandEventHandler(wxwin_project::on_ask_filename
), NULL
, this);
568 mainblock
->Add(fileblock2
, 0, wxGROW
);
572 new_sizer
->Add(mainblock
, 0, wxGROW
);
575 new_sizer
->Add(new wxStaticText(new_panel
, wxID_ANY
, wxT("Authors (one per line):")), 0, wxGROW
);
576 new_sizer
->Add(authors
= new wxTextCtrl(new_panel
, wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
577 wxTE_MULTILINE
), 0, wxGROW
);
578 authors
->Connect(wxEVT_COMMAND_TEXT_UPDATED
, wxCommandEventHandler(wxwin_project::on_filename_change
), NULL
,
581 toplevel
->Add(new_panel
, 1, wxGROW
);
584 wxBoxSizer
* buttonbar
= new wxBoxSizer(wxHORIZONTAL
);
585 buttonbar
->Add(load
= new wxButton(this, wxID_ANY
, wxT("Load")), 0, wxGROW
);
586 buttonbar
->AddStretchSpacer();
587 buttonbar
->Add(quit
= new wxButton(this, wxID_CANCEL
, wxT("Cancel")), 0, wxGROW
);
588 load
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
589 wxCommandEventHandler(wxwin_project::on_load
), NULL
, this);
590 quit
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
,
591 wxCommandEventHandler(wxwin_project::on_quit
), NULL
, this);
592 toplevel
->Add(buttonbar
, 0, wxGROW
);
594 //This gets re-enabled later if needed.
597 on_filename_change(e2
);
599 mainblock
->SetSizeHints(this);
600 new_sizer
->SetSizeHints(this);
601 toplevel
->SetSizeHints(this);
605 wxwin_project::~wxwin_project()
609 void wxwin_project::on_ask_filename(wxCommandEvent
& e
)
614 if(id
>= ASK_SRAMS_BASE
&& id
<= ASK_SRAMS_LAST
) {
615 std::string fname
= pick_file_member(this, "Choose " + sram_names
[id
- ASK_SRAMS_BASE
], ".");
616 sram_files
[sram_names
[id
- ASK_SRAMS_BASE
]]->SetValue(towxstring(fname
));
618 on_filename_change(e
);
619 } catch(canceled_exception
& e
) {
623 void wxwin_project::on_filename_change(wxCommandEvent
& e
)
627 boost::lexical_cast
<int64_t>(tostdstring(rtc_sec
->GetValue()));
628 if(boost::lexical_cast
<int64_t>(tostdstring(rtc_subsec
->GetValue())) < 0)
630 size_t lines
= authors
->GetNumberOfLines();
631 for(size_t i
= 0; i
< lines
; i
++) {
632 std::string l
= tostdstring(authors
->GetLineText(i
));
642 void wxwin_project::on_quit(wxCommandEvent
& e
)
647 void wxwin_project::on_load(wxCommandEvent
& e
)
651 moviefile
& mov
= make_movie();
652 mov
.start_paused
= false;
653 rrdata_set tmp_rdata
;
654 mov
.save("$MEMORY:wxwidgets-romload-tmp", 0, true, tmp_rdata
);
655 inst
.iqueue
->queue("load-state $MEMORY:wxwidgets-romload-tmp");
657 } catch(std::exception
& e
) {
658 show_message_ok(this, "Error loading movie", e
.what(), wxICON_EXCLAMATION
);
663 struct moviefile
& wxwin_project::make_movie()
666 moviefile
& f
= *new moviefile
;
667 f
.force_corrupt
= false;
668 f
.gametype
= &inst
.rom
->get_sysregion();
669 for(auto i
: settings
) {
670 f
.settings
[i
.first
] = i
.second
.read();
671 if(!i
.second
.get_setting().validate(f
.settings
[i
.first
]))
672 throw std::runtime_error((stringfmt() << "Bad value for setting " << i
.first
).str());
674 f
.coreversion
= inst
.rom
->get_core_identifier();
675 f
.gamename
= tostdstring(projectname
->GetValue());
676 f
.projectid
= get_random_hexstring(40);
677 set_mprefix_for_project(f
.projectid
, tostdstring(prefix
->GetValue()));
679 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
680 f
.romimg_sha256
[i
] = inst
.rom
->romimg
[i
].sha_256
.read();
681 f
.romxml_sha256
[i
] = inst
.rom
->romxml
[i
].sha_256
.read();
682 f
.namehint
[i
] = inst
.rom
->romimg
[i
].namehint
;
684 size_t lines
= authors
->GetNumberOfLines();
685 for(size_t i
= 0; i
< lines
; i
++) {
686 std::string l
= tostdstring(authors
->GetLineText(i
));
687 if(l
!= "" && l
!= "|")
688 f
.authors
.push_back(split_author(l
));
690 for(auto i
: sram_files
) {
691 std::string sf
= tostdstring(i
.second
->GetValue());
692 std::vector
<char>* target
;
694 target
= &(f
.movie_sram
[i
.first
]);
696 target
= &(f
.anchor_savestate
);
699 if(moviefile::is_movie_or_savestate(sf
)) {
700 moviefile::sram_extractor
e(sf
);
701 e
.read(i
.first
, *target
);
703 *target
= zip::readrel(sf
, "");
706 f
.is_savestate
= false;
707 f
.movie_rtc_second
= f
.rtc_second
= boost::lexical_cast
<int64_t>(tostdstring(rtc_sec
->GetValue()));
708 f
.movie_rtc_subsecond
= f
.rtc_subsecond
= boost::lexical_cast
<int64_t>(tostdstring(rtc_subsec
->GetValue()));
709 if(f
.movie_rtc_subsecond
< 0)
710 throw std::runtime_error("RTC subsecond must be positive");
711 auto ctrldata
= inst
.rom
->controllerconfig(f
.settings
);
712 portctrl::type_set
& ports
= portctrl::type_set::make(ctrldata
.ports
, ctrldata
.portindex());
713 f
.create_default_branch(ports
);
717 void open_new_project_window(wxWindow
* parent
, emulator_instance
& inst
)
720 if(inst
.rom
->isnull()) {
721 show_message_ok(parent
, "Can't start new project", "No ROM loaded", wxICON_EXCLAMATION
);
724 wxwin_newproject
* projwin
= new wxwin_newproject(parent
, inst
);
725 projwin
->ShowModal();