lsnes/platform/wxwidgets/src/project_select_window.cpp
Ilari Liusvaara b497bd7ed6 Wxwidgets graphics plugin
As opposed to SDL graphics plugin, this has full GUI.
2011-11-05 20:46:18 +02:00

252 lines
8.2 KiB
C++

#include "lsnes.hpp"
#include <snes/snes.hpp>
#include <ui-libsnes/libsnes.hpp>
#include "project_select_window.hpp"
#include "common.hpp"
#include "zip.hpp"
#include "moviedata.hpp"
#include "emufn.hpp"
#include <stdexcept>
#include <boost/lexical_cast.hpp>
namespace
{
std::string sram_name(const nall::string& _id, SNES::Cartridge::Slot slotname)
{
std::string id(_id, _id.length());
if(slotname == SNES::Cartridge::Slot::SufamiTurboA)
return "slota." + id.substr(1);
if(slotname == SNES::Cartridge::Slot::SufamiTurboB)
return "slotb." + id.substr(1);
return id.substr(1);
}
porttype_t get_controller_type(const std::string& s)
{
if(s == CNAME_NONE)
return PT_NONE;
if(s == CNAME_GAMEPAD)
return PT_GAMEPAD;
if(s == CNAME_MULTITAP)
return PT_MULTITAP;
if(s == CNAME_MOUSE)
return PT_MOUSE;
if(s == CNAME_SUPERSCOPE)
return PT_SUPERSCOPE;
if(s == CNAME_JUSTIFIER)
return PT_JUSTIFIER;
if(s == CNAME_JUSTIFIERS)
return PT_JUSTIFIERS;
return PT_INVALID;
}
}
wx_project_select_window::wx_project_select_window(loaded_rom& rom)
: wxFrame(NULL, wxID_ANY, wxT("Project settings"), wxDefaultPosition, wxSize(-1, -1),
primary_window_style)
{
our_rom = &rom;
wxString cchoices[7];
cchoices[0] = wxT(CNAME_NONE);
cchoices[1] = wxT(CNAME_GAMEPAD);
cchoices[2] = wxT(CNAME_MULTITAP);
cchoices[3] = wxT(CNAME_MOUSE);
cchoices[4] = wxT(CNAME_SUPERSCOPE);
cchoices[5] = wxT(CNAME_JUSTIFIER);
cchoices[6] = wxT(CNAME_JUSTIFIERS);
std::set<std::string> sram_set = get_sram_set();
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(7 + sram_set.size(), 1, 0, 0);
SetSizer(top_s);
wxRadioButton* file = new wxRadioButton(this, wxID_ANY, wxT("Load movie/savestate"), wxDefaultPosition,
wxDefaultSize, wxRB_GROUP);
wxRadioButton* newp = new wxRadioButton(this, wxID_ANY, wxT("New project"));
file->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
wxCommandEventHandler(wx_project_select_window::on_file_select), NULL, this);
newp->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
wxCommandEventHandler(wx_project_select_window::on_new_select), NULL, this);
top_s->Add(file, 0, wxGROW);
top_s->Add(newp, 0, wxGROW);
load_file = true;
filename = new filenamebox(top_s, this, "Movie/Savestate", FNBF_PL | FNBF_OI, this,
wxCommandEventHandler(wx_project_select_window::on_filename_change));
wxFlexGridSizer* c_s = new wxFlexGridSizer(4, 2, 0, 0);
controller1type = new labeledcombobox(c_s, this, "Controller 1 type:", cchoices, 4, 1, false, this,
wxCommandEventHandler(wx_project_select_window::on_filename_change));
controller2type = new labeledcombobox(c_s, this, "Controller 2 type:", cchoices, 7, 0, false, this,
wxCommandEventHandler(wx_project_select_window::on_filename_change));
c_s->Add(new wxStaticText(this, wxID_ANY, wxT("Initial RTC:")), 0, wxGROW);
wxFlexGridSizer* t_s = new wxFlexGridSizer(1, 3, 0, 0);
t_s->Add(rtc_sec = new wxTextCtrl(this, wxID_ANY, wxT("1000000000"), wxDefaultPosition, wxSize(150, -1)), 1,
wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT(":")), 0, wxGROW);
t_s->Add(rtc_subsec = new wxTextCtrl(this, wxID_ANY, wxT("0"), wxDefaultPosition, wxSize(120, -1)), 0, wxGROW);
rtc_sec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
wxCommandEventHandler(wx_project_select_window::on_filename_change), NULL, this);
rtc_subsec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
wxCommandEventHandler(wx_project_select_window::on_filename_change), NULL, this);
c_s->Add(t_s, 0, wxGROW);
top_s->Add(c_s, 0, wxGROW);
c_s->Add(new wxStaticText(this, wxID_ANY, wxT("Game name:")), 0, wxGROW);
c_s->Add(projectname = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)), 1, wxGROW);
top_s->Add(new wxStaticText(this, wxID_ANY, wxT("Authors (one per line):")), 0, wxGROW);
top_s->Add(authors = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE), 0, wxGROW);
authors->Connect(wxEVT_COMMAND_TEXT_UPDATED,
wxCommandEventHandler(wx_project_select_window::on_filename_change), NULL, this);
for(auto i : sram_set)
srams[i] = new filenamebox(top_s, this, "SRAM " + i + ":" , FNBF_PL | FNBF_OI, this,
wxCommandEventHandler(wx_project_select_window::on_filename_change));
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(load = new wxButton(this, wxID_ANY, wxT("Load")), 0, wxGROW);
pbutton_s->Add(quit = new wxButton(this, wxID_EXIT, wxT("Quit")), 0, wxGROW);
load->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_project_select_window::on_load), NULL, this);
quit->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_project_select_window::on_quit), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
wxCommandEvent e;
on_file_select(e);
t_s->SetSizeHints(this);
c_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
}
wx_project_select_window::~wx_project_select_window()
{
delete controller1type;
delete controller2type;
delete filename;
}
void wx_project_select_window::on_file_select(wxCommandEvent& e)
{
filename->enable();
controller1type->disable();
controller2type->disable();
rtc_sec->Disable();
rtc_subsec->Disable();
projectname->Disable();
authors->Disable();
load->SetLabel(wxT("Load"));
on_filename_change(e);
load_file = true;
for(auto i : srams)
i.second->disable();
}
void wx_project_select_window::on_new_select(wxCommandEvent& e)
{
filename->disable();
controller1type->enable();
controller2type->enable();
rtc_sec->Enable();
rtc_subsec->Enable();
projectname->Enable();
authors->Enable();
load->SetLabel(wxT("Start"));
on_filename_change(e);
load_file = false;
for(auto i : srams)
i.second->enable();
}
void wx_project_select_window::on_filename_change(wxCommandEvent& e)
{
if(filename->is_enabled()) {
load->Enable(filename->is_nonblank());
} else {
try {
boost::lexical_cast<int64_t>(tostdstring(rtc_sec->GetValue()));
if(boost::lexical_cast<int64_t>(tostdstring(rtc_subsec->GetValue())) < 0)
throw 42;
size_t lines = authors->GetNumberOfLines();
for(size_t i = 0; i < lines; i++) {
std::string l = tostdstring(authors->GetLineText(i));
if(l == "|")
throw 43;
}
load->Enable();
} catch(...) {
load->Disable();
}
}
}
void wx_project_select_window::on_quit(wxCommandEvent& e)
{
Close(true);
}
void wx_project_select_window::on_load(wxCommandEvent& e)
{
try {
if(load_file) {
boot_emulator(*our_rom, *new moviefile(filename->get_file()));
} else {
boot_emulator(*our_rom, *new moviefile(make_movie()));
}
Destroy();
} catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
wxT("Error loading movie"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
return;
}
}
std::set<std::string> wx_project_select_window::get_sram_set()
{
std::set<std::string> r;
for(unsigned i = 0; i < SNES::cartridge.nvram.size(); i++) {
SNES::Cartridge::NonVolatileRAM& s = SNES::cartridge.nvram[i];
r.insert(sram_name(s.id, s.slot));
}
return r;
}
struct moviefile wx_project_select_window::make_movie()
{
moviefile f;
f.force_corrupt = false;
f.gametype = gtype::togametype(our_rom->rtype, our_rom->region);
f.port1 = get_controller_type(controller1type->get_choice());
f.port2 = get_controller_type(controller2type->get_choice());
f.coreversion = bsnes_core_version;
f.gamename = tostdstring(projectname->GetValue());
f.projectid = get_random_hexstring(40);
f.rerecords = "0";
f.rom_sha256 = our_rom->rom.sha256;
f.romxml_sha256 = our_rom->rom_xml.sha256;
f.slota_sha256 = our_rom->slota.sha256;
f.slotaxml_sha256 = our_rom->slota_xml.sha256;
f.slotb_sha256 = our_rom->slotb.sha256;
f.slotbxml_sha256 = our_rom->slotb_xml.sha256;
size_t lines = authors->GetNumberOfLines();
for(size_t i = 0; i < lines; i++) {
std::string l = tostdstring(authors->GetLineText(i));
if(l != "" && l != "|")
f.authors.push_back(split_author(l));
}
for(auto i : srams)
if(i.second->get_file() != "")
f.movie_sram[i.first] = read_file_relative(i.second->get_file(), "");
f.is_savestate = false;
f.movie_rtc_second = f.rtc_second = boost::lexical_cast<int64_t>(tostdstring(rtc_sec->GetValue()));
f.movie_rtc_subsecond = f.rtc_subsecond = boost::lexical_cast<int64_t>(tostdstring(rtc_subsec->GetValue()));
if(f.movie_rtc_subsecond < 0)
throw std::runtime_error("RTC subsecond must be positive");
return f;
}