Fix zero luma corner case
[lsnes.git] / src / plat-wxwidgets / rom_patch_window.cpp
blob5796c6f1174cbd7b15e3138cebfc6328a4bc45cc
1 #include "lsnes.hpp"
2 #include <snes/snes.hpp>
3 #include <ui-libsnes/libsnes.hpp>
5 #include "core/framerate.hpp"
6 #include "core/zip.hpp"
8 #include "plat-wxwidgets/callrom.hpp"
9 #include "plat-wxwidgets/project_select_window.hpp"
10 #include "plat-wxwidgets/rom_patch_window.hpp"
12 namespace
14 class my_interfaced : public SNES::Interface
16 string path(SNES::Cartridge::Slot slot, const string &hint)
18 return "./";
20 } simple_interface;
23 wx_rom_patch_window::wx_rom_patch_window(loaded_rom& rom)
24 : wxFrame(NULL, wxID_ANY, wxT("Patch ROM"), wxDefaultPosition, wxSize(-1, -1),
25 primary_window_style)
27 our_rom = &rom;
28 size_t target_count = fill_rom_names(rom.rtype, targets);
30 Centre();
31 wxFlexGridSizer* top_s = new wxFlexGridSizer(5, 1, 0, 0);
32 SetSizer(top_s);
34 wxFlexGridSizer* checksums_s = new wxFlexGridSizer(target_count, 2, 0, 0);
35 for(unsigned i = 0; i < 6; i++)
36 checksums[i] = NULL;
37 for(unsigned i = 0; i < target_count; i++) {
38 checksums_s->Add(new wxStaticText(this, wxID_ANY, targets[i]), 0, wxGROW);
39 checksums_s->Add(checksums[i] = new wxStaticText(this, wxID_ANY,
40 towxstring(get_rom_slot(*our_rom, i).sha256)), 0, wxGROW);
42 top_s->Add(checksums_s, 0, wxGROW);
44 wxFlexGridSizer* pwhat_s = new wxFlexGridSizer(1, 2, 0, 0);
45 pwhat_s->Add(new wxStaticText(this, wxID_ANY, wxT("Patch what:")), 0, wxGROW);
46 pwhat_s->Add(patch_what = new wxComboBox(this, wxID_ANY, targets[0], wxDefaultPosition, wxDefaultSize,
47 target_count, targets, wxCB_READONLY), 0, wxGROW);
48 top_s->Add(pwhat_s, 0, wxGROW);
50 patchfile = new filenamebox(top_s, this, "Patch file", FNBF_PL | FNBF_OI | FNBF_PZ, this,
51 wxCommandEventHandler(wx_rom_patch_window::on_patchfile_change));
53 wxFlexGridSizer* poffset_s = new wxFlexGridSizer(1, 2, 0, 0);
54 pwhat_s->Add(new wxStaticText(this, wxID_ANY, wxT("Patch offset:")), 0, wxGROW);
55 pwhat_s->Add(patch_offset = new wxTextCtrl(this, wxID_ANY, wxT("")), 0, wxGROW);
56 patch_offset->Connect(wxEVT_COMMAND_TEXT_UPDATED,
57 wxCommandEventHandler(wx_rom_patch_window::on_patchfile_change), NULL, this);
58 top_s->Add(poffset_s, 0, wxGROW);
60 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
61 pbutton_s->AddStretchSpacer();
62 wxButton* thats_enough = new wxButton(this, wxID_ANY, wxT("Enough"));
63 pbutton_s->Add(thats_enough, 0, wxGROW);
64 thats_enough->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
65 wxCommandEventHandler(wx_rom_patch_window::on_done), NULL, this);
66 dopatch = new wxButton(this, wxID_ANY, wxT("Patch"));
67 pbutton_s->Add(dopatch, 0, wxGROW);
68 dopatch->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
69 wxCommandEventHandler(wx_rom_patch_window::on_do_patch), NULL, this);
70 dopatch->Disable();
71 wxButton* quitbutton = new wxButton(this, wxID_EXIT, wxT("Quit"));
72 pbutton_s->Add(quitbutton, 0, wxGROW);
73 quitbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
74 wxCommandEventHandler(wx_rom_patch_window::on_quit), NULL, this);
75 top_s->Add(pbutton_s, 0, wxGROW);
77 patch_offset->SetValue(wxT("0"));
79 checksums_s->SetSizeHints(this);
80 pwhat_s->SetSizeHints(this);
81 pbutton_s->SetSizeHints(this);
82 top_s->SetSizeHints(this);
83 Fit();
86 wx_rom_patch_window::~wx_rom_patch_window()
88 delete patchfile;
91 void wx_rom_patch_window::on_patchfile_change(wxCommandEvent& e)
93 //std::cerr << "wx_rom_patch_window::on_patchfile_change" << std::endl;
94 bool ok = true;
95 //std::cerr << "wx_rom_patch_window::on_patchfile_change: #1: ok=" << ok << std::endl;
96 ok = ok && patchfile->is_nonblank();
97 //std::cerr << "wx_rom_patch_window::on_patchfile_change: #2: ok=" << ok << std::endl;
98 std::string offsetv = tostdstring(patch_offset->GetValue());
99 try {
100 int32_t offset = boost::lexical_cast<int32_t>(offsetv);
101 } catch(...) {
102 ok = false;
104 //std::cerr << "wx_rom_patch_window::on_patchfile_change: #3: ok=" << ok << std::endl;
105 if(dopatch) {
106 //std::cerr << "wx_rom_patch_window::on_patchfile_change: #4: ok=" << ok << std::endl;
107 dopatch->Enable(ok);
109 //std::cerr << "wx_rom_patch_window::on_patchfile_change: #5: ok=" << ok << std::endl;
112 void wx_rom_patch_window::on_do_patch(wxCommandEvent& e)
114 try {
115 auto patch_contents = read_file_relative(patchfile->get_file(), "");
116 size_t patch_index = romname_to_index(our_rom->rtype, patch_what->GetValue());
117 if(patch_index == 6)
118 throw std::runtime_error("Internal error: Patch WHAT?");
119 loaded_slot& s = get_rom_slot(*our_rom, patch_index);
120 std::string offsetv = tostdstring(patch_offset->GetValue());
121 int32_t offset = boost::lexical_cast<int32_t>(offsetv);
122 s.patch(patch_contents, offset);
123 checksums[patch_index]->SetLabel(towxstring(s.sha256));
124 } catch(std::exception& e) {
125 wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
126 wxT("Error patching ROM"), wxOK | wxICON_EXCLAMATION);
127 d->ShowModal();
128 return;
130 patchfile->clear();
133 void wx_rom_patch_window::on_quit(wxCommandEvent& e)
135 Close(true);
138 void wx_rom_patch_window::on_done(wxCommandEvent& e)
140 try {
141 SNES::interface = &simple_interface;
142 our_rom->load();
143 } catch(std::exception& e) {
144 wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
145 wxT("Error loading ROM"), wxOK | wxICON_EXCLAMATION);
146 d->ShowModal();
147 return;
149 messages << "Detected region: " << gtype::tostring(our_rom->rtype, our_rom->region) << std::endl;
150 if(our_rom->region == REGION_PAL)
151 set_nominal_framerate(322445.0/6448.0);
152 else if(our_rom->region == REGION_NTSC)
153 set_nominal_framerate(10738636.0/178683.0);
155 messages << "--- Internal memory mappings ---" << std::endl;
156 dump_region_map();
157 messages << "--- End of Startup --- " << std::endl;
158 wx_project_select_window* projwin = new wx_project_select_window(*our_rom);
159 projwin->Show();
160 Destroy();