Wxwidgets graphics plugin

As opposed to SDL graphics plugin, this has full GUI.
This commit is contained in:
Ilari Liusvaara 2011-11-05 20:46:18 +02:00
parent 7b3fc13b22
commit b497bd7ed6
33 changed files with 4184 additions and 50 deletions

View file

@ -104,8 +104,16 @@ endif
platform/SDL/%.$(OBJECT_SUFFIX): platform/SDL/%.cpp
$(REALCC) -I. -Igeneric -g -std=gnu++0x -I$(BSNES_PATH) -c -o $@ $< $(CFLAGS) $(PLATFORM_CFLAGS)
else
ifeq ($(GRAPHICS), WXWIDGETS)
PLATFORM_OBJECTS += platform/wxwidgets/main-wxwidgets.$(OBJECT_SUFFIX) $(patsubst %.cpp,%.$(OBJECT_SUFFIX),$(wildcard platform/wxwidgets/src/*.cpp))
PLATFORM_CFLAGS += $(shell $(CROSS_PREFIX)wx-config --cxxflags) $(shell $(CROSS_PREFIX)pkg-config libswscale --cflags)
PLATFORM_LDFLAGS += $(shell $(CROSS_PREFIX)wx-config --libs) $(shell $(CROSS_PREFIX)pkg-config libswscale --libs)
platform/wxwidgets/%.$(OBJECT_SUFFIX): platform/wxwidgets/%.cpp
$(REALCC) -I. -Igeneric -g -std=gnu++0x -I$(BSNES_PATH) -c -o $@ $< $(CFLAGS) $(PLATFORM_CFLAGS)
else
$(error "Unsupported graphics type")
endif
endif
.PRECIOUS: %.$(EXECUTABLE_SUFFIX) %.$(OBJECT_SUFFIX)
@ -129,4 +137,4 @@ fonts/parsehexfont.$(EXECUTABLE_SUFFIX): fonts/parsehexfont.cpp
$(HOSTCC) -std=gnu++0x $(HOSTCCFLAGS) -o $@ $^
clean:
rm -f $(PROGRAMS) $(patsubst %.$(EXECUTABLE_SUFFIX),%.$(OBJECT_SUFFIX),$(PROGRAMS)) platform/*/*.$(OBJECT_SUFFIX) avidump/*.$(OBJECT_SUFFIX) generic/*.$(OBJECT_SUFFIX) lua/*.$(OBJECT_SUFFIX) fonts/font.o fonts/font.cpp
rm -f $(PROGRAMS) $(patsubst %.$(EXECUTABLE_SUFFIX),%.$(OBJECT_SUFFIX),$(PROGRAMS)) platform/*/*.$(OBJECT_SUFFIX) platform/*/src/*.$(OBJECT_SUFFIX) avidump/*.$(OBJECT_SUFFIX) generic/*.$(OBJECT_SUFFIX) lua/*.$(OBJECT_SUFFIX) fonts/font.o fonts/font.cpp

141
generic/coroutine.cpp Normal file
View file

@ -0,0 +1,141 @@
#include "coroutine.hpp"
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
namespace
{
#if defined(__amd64__)
void trampoline_fn(void (*fn)(void* arg), void* arg) __attribute__((sysv_abi));
#else
#if defined(__i386__)
void trampoline_fn(void (*fn)(void* arg), void* arg) __attribute__((stdcall));
#else
#error "This CPU is not supported"
#endif
#endif
void trampoline_fn(void (*fn)(void* arg), void* arg)
{
fn(arg);
coroutine::cexit();
}
#ifdef __amd64__
bool stacks_grow_down = true;
void switch_stacks(void (*fn)(void* arg), void* arg, void* new_esp)
{
__asm__ __volatile__("movq %%rax,%%rsp; call *%%rdx" :: "D"(fn), "S"(arg), "a"(new_esp), "d"(trampoline_fn));
}
#else
#ifdef __i386__
bool stacks_grow_down = true;
void switch_stacks(void (*fn)(void* arg), void* arg, void* new_esp)
{
__asm__ __volatile__("movl %%eax,%%esp; pushl %%esi; push %%edi ; call *%%edx" :: "D"(fn), "S"(arg),
"a"(new_esp), "d"(trampoline_fn));
}
#else
#error "This CPU is not supported"
#endif
#endif
jmp_buf main_saved_env;
coroutine* executing_coroutine = NULL;
}
coroutine::coroutine(void (*fn)(void* arg), void* arg, size_t stacksize)
{
dead = false;
if(executing_coroutine) {
std::cerr << "FATAL: Coroutine create only allowed from main coroutine!" << std::endl;
exit(1);
}
executing_coroutine = this;
if(setjmp(main_saved_env)) {
executing_coroutine = NULL;
return;
}
stackblock = new unsigned char[stacksize];
unsigned char* esp = stackblock;
if(stacks_grow_down)
esp = esp + stacksize;
switch_stacks(fn, arg, esp);
}
coroutine::~coroutine() throw()
{
if(!dead) {
std::cerr << "FATAL: Trying to delete a live coroutine!" << std::endl;
exit(1);
}
delete[] stackblock;
}
void coroutine::resume()
{
if(executing_coroutine) {
std::cerr << "FATAL: Coroutine resume only allowed from main coroutine!" << std::endl;
exit(1);
}
if(dead)
return;
executing_coroutine = this;
if(setjmp(main_saved_env)) {
executing_coroutine = NULL;
return;
}
longjmp(saved_env, 1);
}
void coroutine::yield()
{
if(!executing_coroutine) {
std::cerr << "FATAL: Coroutine yield not allowed from main coroutine!" << std::endl;
exit(1);
}
if(setjmp(executing_coroutine->saved_env))
return;
longjmp(main_saved_env, 1);
}
bool coroutine::is_dead()
{
return dead;
}
void coroutine::cexit()
{
if(!executing_coroutine) {
std::cerr << "FATAL: Main coroutine can't exit!" << std::endl;
exit(1);
}
executing_coroutine->dead = true;
yield();
}
#ifdef TEST_COROUTINES
void fn(void* arg)
{
std::cout << "Print #1 from coroutine (" << arg << ")" << std::endl;
coroutine::yield();
std::cout << "Print #2 from coroutine (" << arg << ")" << std::endl;
coroutine::yield();
std::cout << "Print #3 from coroutine (" << arg << ")" << std::endl;
}
int main()
{
int x;
coroutine c(fn, &x, 8 * 1024 * 1024);
std::cout << "Back to main thread" << std::endl;
std::cout << "Coroutine dead flag is " << c.is_dead() << std::endl;
c.resume();
std::cout << "Back to main thread" << std::endl;
std::cout << "Coroutine dead flag is " << c.is_dead() << std::endl;
c.resume();
std::cout << "Back to main thread" << std::endl;
std::cout << "Coroutine dead flag is " << c.is_dead() << std::endl;
return 0;
}
#endif

59
generic/coroutine.hpp Normal file
View file

@ -0,0 +1,59 @@
#ifndef _coroutine__hpp__included__
#define _coroutine__hpp__included__
#include <cstdlib>
#include <csetjmp>
/**
* A coroutine.
*/
class coroutine
{
public:
/**
* Create a new coroutine with specified starting function and stack size. The coroutine created will run until it
* yields for the first time.
*
* This can only be called from outside any coroutine.
*
* parameter fn: The function to call.
* parameter arg: Argument to pass to the function.
* parameter stacksize: Size of stack to allocate for function.
* throws std::bad:alloc: Not enough memory.
*/
coroutine(void (*fn)(void* arg), void* arg, size_t stacksize);
/**
* Destructor.
*/
~coroutine() throw();
/**
* Resume yielded coroutine.
*
* This can only be called from outside any coroutine.
*/
void resume();
/**
* Yield execution, causing coroutine::resume() or coroutine::coroutine() that called this coroutine to return.
*
* This can only be called from coroutine.
*/
static void yield();
/**
* Is the coroutine dead (has returned?)
*/
bool is_dead();
/**
* Exit the coroutine (yield and mark it dead).
*/
static void cexit();
private:
jmp_buf saved_env;
bool dead;
unsigned char* stackblock;
};
#endif

View file

@ -814,7 +814,7 @@ Print all aliases and their expansions in effect.
\end_layout
\begin_layout Subsection
run-script <script>
run-script <script> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1076,7 +1076,7 @@ These commands are not available in lsnesrc, but are available after ROM
\end_layout
\begin_layout Subsubsection
quit-emulator [/y]
quit-emulator [/y] (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1085,7 +1085,7 @@ Quits the emulator (asking for confirmation).
\end_layout
\begin_layout Subsubsection
pause-emulator
pause-emulator (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1093,7 +1093,7 @@ Toggle paused/unpaused
\end_layout
\begin_layout Subsubsection
+advance-frame
+advance-frame (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1103,7 +1103,7 @@ Advance frame.
\end_layout
\begin_layout Subsubsection
+advance-poll
+advance-poll (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1113,7 +1113,7 @@ Advance subframe.
\end_layout
\begin_layout Subsubsection
advance-skiplag
advance-skiplag (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1121,7 +1121,7 @@ Skip to first poll in frame after current.
\end_layout
\begin_layout Subsubsection
reset
reset (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1129,7 +1129,7 @@ Reset the SNES after this frame.
\end_layout
\begin_layout Subsubsection
load <filename>
load <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1137,7 +1137,7 @@ Load savestate <filename> in current mode.
\end_layout
\begin_layout Subsubsection
load-state <filename>
load-state <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1145,7 +1145,7 @@ Load savestate <filename> in readwrite mode.
\end_layout
\begin_layout Subsubsection
load-readonly <filename>
load-readonly <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1153,7 +1153,7 @@ Load savestate <filename> in readonly mode.
\end_layout
\begin_layout Subsubsection
load-preserve <filename>
load-preserve <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1161,7 +1161,7 @@ Load savestate <filename> in readonly mode, preserving current events.
\end_layout
\begin_layout Subsubsection
load-movie <filename>
load-movie <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1169,7 +1169,7 @@ Load savestate <filename>, ignoring save part in readonly mode.
\end_layout
\begin_layout Subsubsection
save-state <filename>
save-state <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1177,7 +1177,7 @@ Save system state to <filename> as soon as possible.
\end_layout
\begin_layout Subsubsection
save-movie <filename>
save-movie <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1185,7 +1185,7 @@ Save movie to <filename>.
\end_layout
\begin_layout Subsubsection
set-rwmode
set-rwmode (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1193,7 +1193,7 @@ Set read-write mode.
\end_layout
\begin_layout Subsubsection
set-romode
set-romode (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1201,7 +1201,7 @@ Set read-only mode
\end_layout
\begin_layout Subsubsection
toggle-rwmode
toggle-rwmode (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1209,7 +1209,7 @@ Toggle between read-only and read-write modes.
\end_layout
\begin_layout Subsubsection
set-gamename <name>
set-gamename <name> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1217,7 +1217,7 @@ Set name of the game to <name>
\end_layout
\begin_layout Subsubsection
get-gamename
get-gamename (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1225,7 +1225,7 @@ Print the name of the game.
\end_layout
\begin_layout Subsubsection
add-author <author>
add-author <author> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1235,7 +1235,7 @@ Adds new author <author>.
\end_layout
\begin_layout Subsubsection
edit-author <num> <author>
edit-author <num> <author> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1244,7 +1244,7 @@ Edit the author in slot <num> (0-based) to be <author> (see add-author for
\end_layout
\begin_layout Subsubsection
remove-author <num>
remove-author <num> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1252,7 +1252,7 @@ Remove author in slot <num>
\end_layout
\begin_layout Subsubsection
print-authors
print-authors (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1260,7 +1260,7 @@ Print authors.
\end_layout
\begin_layout Subsubsection
test-1, test-2, test-3
test-1, test-2, test-3 (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1269,7 +1269,7 @@ Internal test commands.
\end_layout
\begin_layout Subsubsection
take-screenshot <filename>
take-screenshot <filename> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1277,7 +1277,7 @@ Save screenshot to <filename>.
\end_layout
\begin_layout Subsubsection
+controller<num><button>
+controller<num><button> (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1360,6 +1360,7 @@ Hold/unhold button <button> on controller <num> (1-8).
\begin_layout Subsubsection
autofire (<pattern>|-)...
(N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1370,7 +1371,7 @@ Set autofire pattern.
\end_layout
\begin_layout Subsubsection
repaint
repaint (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1378,11 +1379,11 @@ Force a repaint.
\end_layout
\begin_layout Subsection
Save jukebox
Save jukebox (implemented for wxwidgets)
\end_layout
\begin_layout Subsubsection
cycle-jukebox-backward
cycle-jukebox-backward (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1390,7 +1391,7 @@ Cycle save jukebox backwards.
\end_layout
\begin_layout Subsubsection
cycle-jukebox-forward
cycle-jukebox-forward (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1398,7 +1399,7 @@ Cycle save jukebox forwards
\end_layout
\begin_layout Subsubsection
add-jukebox-save <filename>
add-jukebox-save <filename> (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1406,7 +1407,7 @@ Add <filename> to jukebox saves.
\end_layout
\begin_layout Subsubsection
load-jukebox
load-jukebox (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1414,7 +1415,7 @@ Do load from jukebox (current mode).
\end_layout
\begin_layout Subsubsection
save-jukebox
save-jukebox (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1422,7 +1423,7 @@ Do state save to jukebox.
\end_layout
\begin_layout Subsection
Lua
Lua (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1430,7 +1431,8 @@ Only available if lua support is compiled in.
\end_layout
\begin_layout Subsubsection
evaluate-lua <luacode>
<<<<<<< HEADevaluate-lua <luacode>=======eval-lua <luacode> (implemented
for wxwidgets)>>>>>>> Wxwidgets Graphics plugin WIP
\end_layout
\begin_layout Standard
@ -1438,7 +1440,7 @@ Run Lua code <luacode> using built-in Lua interpretter.
\end_layout
\begin_layout Subsubsection
run-lua <script>
run-lua <script> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1466,11 +1468,11 @@ Remove a watch.
\end_layout
\begin_layout Subsection
Sound
Sound (implemented for wxwidgets)
\end_layout
\begin_layout Subsubsection
enable-sound <on/off>
enable-sound <on/off> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1478,7 +1480,7 @@ Enable/Disable sound.
\end_layout
\begin_layout Subsubsection
set-sound-device <device>
set-sound-device <device> (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1486,7 +1488,7 @@ Set sound device to <device>
\end_layout
\begin_layout Subsubsection
show-sound-status
show-sound-status (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1494,7 +1496,7 @@ Show status of sound system.
\end_layout
\begin_layout Subsubsection
show-sound-devices
show-sound-devices (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1502,7 +1504,7 @@ Show all available devices.
\end_layout
\begin_layout Subsection
SDL Platform commands
SDL Platform commands (implemented for wxwidgets)
\end_layout
\begin_layout Standard
@ -1510,7 +1512,7 @@ The following are valid on SDL platform.
\end_layout
\begin_layout Subsubsection
identify-key
identify-key (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1518,7 +1520,7 @@ Asks to press a key and then identifies that (pseudo-)key.
\end_layout
\begin_layout Subsubsection
toggle-console
toggle-console (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1526,7 +1528,7 @@ Toggle between windowed/fullscreen console.
\end_layout
\begin_layout Subsubsection
scroll-fullup
scroll-fullup (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1534,7 +1536,7 @@ Scroll messages window as far back as it goes.
\end_layout
\begin_layout Subsubsection
scroll-fulldown
scroll-fulldown (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1542,7 +1544,7 @@ Scroll messages window as far forward as it goes.
\end_layout
\begin_layout Subsubsection
scroll-up
scroll-up (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -1550,7 +1552,7 @@ Scroll messages window back one screenful.
\end_layout
\begin_layout Subsubsection
scroll-down
scroll-down (N/A for wxwidgets)
\end_layout
\begin_layout Standard
@ -3773,12 +3775,20 @@ GRAPHICS=<plat>
\begin_layout Standard
Set graphics platform.
Currently available choice is
Currently available choices are
\begin_inset Quotes eld
\end_inset
SDL
\begin_inset Quotes erd
\end_inset
and
\begin_inset Quotes eld
\end_inset
WXWIDGETS
\begin_inset Quotes erd
\end_inset
.

View file

@ -0,0 +1,71 @@
#include "lsnes.hpp"
#include <snes/snes.hpp>
#include <ui-libsnes/libsnes.hpp>
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include <cassert>
#include "rom.hpp"
#include "avsnoop.hpp"
#include "rrdata.hpp"
#include "framerate.hpp"
#include "zip.hpp"
#include <boost/lexical_cast.hpp>
#include "misc.hpp"
#include "window.hpp"
#include "lua.hpp"
#include "src/rom_select_window.hpp"
#include "src/messages_window.hpp"
#include "src/status_window.hpp"
class lsnes_app : public wxApp
{
public:
virtual bool OnInit();
virtual int OnExit();
};
IMPLEMENT_APP(lsnes_app)
bool lsnes_app::OnInit()
{
set_random_seed();
{
std::ostringstream x;
x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
bsnes_core_version = x.str();
}
window::init();
init_lua();
messages << "BSNES version: " << bsnes_core_version << std::endl;
messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
std::string cfgpath = get_config_path();
messages << "Saving per-user data to: " << get_config_path() << std::endl;
wx_messages_window* msgs = new wx_messages_window();
window1 = msgs;
msgs->Show();
wx_rom_select_window* romwin = new wx_rom_select_window();
romwin->Show();
return true;
}
int lsnes_app::OnExit()
{
av_snooper::_end();
rrdata::close();
window::quit();
return 0;
}
void window::notify_message() throw(std::bad_alloc, std::runtime_error)
{
if(wx_messages_window::ptr)
wx_messages_window::ptr->notify_message();
}

View file

@ -0,0 +1,81 @@
#include "authorseditor.hpp"
#include "common.hpp"
#include "moviedata.hpp"
wx_authors_editor::wx_authors_editor(wxWindow* parent)
: wxDialog(parent, wxID_ANY, wxT("lsnes: Edit game name & authors"), wxDefaultPosition, wxSize(-1, -1))
{
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(4, 1, 0, 0);
SetSizer(top_s);
wxFlexGridSizer* c_s = new wxFlexGridSizer(1, 2, 0, 0);
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(c_s);
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_authors_editor::on_authors_change), NULL, this);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(okbutton = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
okbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_authors_editor::on_ok), NULL, this);
cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_authors_editor::on_cancel), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
c_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
projectname->SetValue(towxstring(our_movie.gamename));
std::string x;
for(auto i : our_movie.authors)
x = x + i.first + "|" + i.second + "\n";
authors->SetValue(towxstring(x));
}
bool wx_authors_editor::ShouldPreventAppExit() const
{
return false;
}
void wx_authors_editor::on_authors_change(wxCommandEvent& e)
{
try {
size_t lines = authors->GetNumberOfLines();
for(size_t i = 0; i < lines; i++) {
std::string l = tostdstring(authors->GetLineText(i));
if(l == "|")
throw 43;
}
okbutton->Enable();
} catch(...) {
okbutton->Disable();
}
}
void wx_authors_editor::on_cancel(wxCommandEvent& e)
{
EndModal(wxID_CANCEL);
}
void wx_authors_editor::on_ok(wxCommandEvent& e)
{
our_movie.gamename = tostdstring(projectname->GetValue());
std::vector<std::pair<std::string, std::string>> newauthors;
size_t lines = authors->GetNumberOfLines();
for(size_t i = 0; i < lines; i++) {
std::string l = tostdstring(authors->GetLineText(i));
if(l != "" && l != "|")
newauthors.push_back(split_author(l));
}
our_movie.authors = newauthors;
EndModal(wxID_OK);
}

View file

@ -0,0 +1,24 @@
#ifndef _wxwidgets_authorseditor__hpp__included__
#define _wxwidgets_authorseditor__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
class wx_authors_editor : public wxDialog
{
public:
wx_authors_editor(wxWindow* parent);
bool ShouldPreventAppExit() const;
void on_authors_change(wxCommandEvent& e);
void on_cancel(wxCommandEvent& e);
void on_ok(wxCommandEvent& e);
private:
wxTextCtrl* projectname;
wxTextCtrl* authors;
wxButton* okbutton;
wxButton* cancel;
};
#endif

View file

@ -0,0 +1,222 @@
#include "axeseditor.hpp"
#include "keymapper.hpp"
#include "common.hpp"
#include <boost/lexical_cast.hpp>
#include <sstream>
#define AMODE_DISABLED "Disabled"
#define AMODE_AXIS_PAIR "Axis"
#define AMODE_AXIS_PAIR_INVERSE "Axis (inverted)"
#define AMODE_PRESSURE_M0 "Pressure - to 0"
#define AMODE_PRESSURE_MP "Pressure - to +"
#define AMODE_PRESSURE_0M "Pressure 0 to -"
#define AMODE_PRESSURE_0P "Pressure 0 to +"
#define AMODE_PRESSURE_PM "Pressure + to -"
#define AMODE_PRESSURE_P0 "Pressure + to 0"
wx_axes_editor_axis::wx_axes_editor_axis(wxSizer* sizer, wxWindow* window, const std::string& name)
{
wxString choices[9];
choices[0] = wxT(AMODE_DISABLED);
choices[1] = wxT(AMODE_AXIS_PAIR);
choices[2] = wxT(AMODE_AXIS_PAIR_INVERSE);
choices[3] = wxT(AMODE_PRESSURE_M0);
choices[4] = wxT(AMODE_PRESSURE_MP);
choices[5] = wxT(AMODE_PRESSURE_0M);
choices[6] = wxT(AMODE_PRESSURE_0P);
choices[7] = wxT(AMODE_PRESSURE_PM);
choices[8] = wxT(AMODE_PRESSURE_P0);
size_t defaultidx = 0;
std::string low;
std::string mid;
std::string high;
std::string tolerance;
keygroup* k = keygroup::lookup_by_name(name);
if(!k)
return;
struct keygroup::parameters p = k->get_parameters();
{
switch(p.ktype) {
case keygroup::KT_DISABLED: defaultidx = 0; break;
case keygroup::KT_AXIS_PAIR: defaultidx = 1; break;
case keygroup::KT_AXIS_PAIR_INVERSE: defaultidx = 2; break;
case keygroup::KT_PRESSURE_M0: defaultidx = 3; break;
case keygroup::KT_PRESSURE_MP: defaultidx = 4; break;
case keygroup::KT_PRESSURE_0M: defaultidx = 5; break;
case keygroup::KT_PRESSURE_0P: defaultidx = 6; break;
case keygroup::KT_PRESSURE_PM: defaultidx = 7; break;
case keygroup::KT_PRESSURE_P0: defaultidx = 8; break;
};
std::ostringstream x1;
std::ostringstream x2;
std::ostringstream x3;
std::ostringstream x4;
x1 << p.cal_left;
x2 << p.cal_center;
x3 << p.cal_right;
x4 << p.cal_tolerance;
low = x1.str();
mid = x2.str();
high = x3.str();
tolerance = x4.str();
}
a_name = name;
sizer->Add(new wxStaticText(window, wxID_ANY, towxstring(name)), 0, wxGROW);
sizer->Add(a_type = new wxComboBox(window, wxID_ANY, choices[defaultidx], wxDefaultPosition, wxDefaultSize,
9, choices, wxCB_READONLY), 0, wxGROW);
sizer->Add(a_low = new wxTextCtrl(window, wxID_ANY, towxstring(low)), 0, wxGROW);
sizer->Add(a_mid = new wxTextCtrl(window, wxID_ANY, towxstring(mid)), 0, wxGROW);
sizer->Add(a_high = new wxTextCtrl(window, wxID_ANY, towxstring(high)), 0, wxGROW);
sizer->Add(a_tolerance = new wxTextCtrl(window, wxID_ANY, towxstring(tolerance)), 0, wxGROW);
a_low->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
window);
a_mid->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
window);
a_high->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
window);
a_tolerance->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
window);
}
bool wx_axes_editor_axis::is_ok()
{
int32_t low, mid, high;
double tolerance;
try {
low = boost::lexical_cast<int32_t>(tostdstring(a_low->GetValue()));
mid = boost::lexical_cast<int32_t>(tostdstring(a_mid->GetValue()));
high = boost::lexical_cast<int32_t>(tostdstring(a_high->GetValue()));
tolerance = boost::lexical_cast<double>(tostdstring(a_tolerance->GetValue()));
} catch(...) {
return false;
}
if(low < -32768 || low > 32767 || low > mid)
return false;
if(mid < -32768 || mid > 32767 || mid > high)
return false;
if(high < -32768 || high > 32767)
return false;
if(tolerance <= 0 || tolerance >= 1)
return false;
return true;
}
void wx_axes_editor_axis::apply()
{
keygroup* k = keygroup::lookup_by_name(a_name);
if(!k)
return;
int32_t low, mid, high;
double tolerance;
enum keygroup::type ntype;
enum keygroup::type ctype = k->get_parameters().ktype;;
std::string amode = tostdstring(a_type->GetValue());
if(amode == AMODE_AXIS_PAIR)
ntype = keygroup::KT_AXIS_PAIR;
if(amode == AMODE_AXIS_PAIR_INVERSE)
ntype = keygroup::KT_AXIS_PAIR_INVERSE;
if(amode == AMODE_DISABLED)
ntype = keygroup::KT_DISABLED;
if(amode == AMODE_PRESSURE_0M)
ntype = keygroup::KT_PRESSURE_0M;
if(amode == AMODE_PRESSURE_0P)
ntype = keygroup::KT_PRESSURE_0P;
if(amode == AMODE_PRESSURE_M0)
ntype = keygroup::KT_PRESSURE_M0;
if(amode == AMODE_PRESSURE_MP)
ntype = keygroup::KT_PRESSURE_MP;
if(amode == AMODE_PRESSURE_PM)
ntype = keygroup::KT_PRESSURE_PM;
if(amode == AMODE_PRESSURE_P0)
ntype = keygroup::KT_PRESSURE_P0;
try {
low = boost::lexical_cast<int32_t>(tostdstring(a_low->GetValue()));
mid = boost::lexical_cast<int32_t>(tostdstring(a_mid->GetValue()));
high = boost::lexical_cast<int32_t>(tostdstring(a_high->GetValue()));
tolerance = boost::lexical_cast<double>(tostdstring(a_tolerance->GetValue()));
} catch(...) {
return;
}
if(low < -32768 || low > 32767 || low > mid)
return;
if(mid < -32768 || mid > 32767 || mid > high)
return;
if(high < -32768 || high > 32767)
return;
if(tolerance <= 0 || tolerance >= 1)
return;
if(ctype != ntype)
k->change_type(ntype);
k->change_calibration(low, mid, high, tolerance);
}
wx_axes_editor::wx_axes_editor(wxWindow* parent)
: wxDialog(parent, wxID_ANY, wxT("lsnes: Edit axes"), wxDefaultPosition, wxSize(-1, -1))
{
std::set<std::string> axisnames = keygroup::get_axis_set();
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
SetSizer(top_s);
wxFlexGridSizer* t_s = new wxFlexGridSizer(axisnames.size() + 1, 6, 0, 0);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Name")), 0, wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Type")), 0, wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Low")), 0, wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Mid")), 0, wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("High")), 0, wxGROW);
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Tolerance")), 0, wxGROW);
for(auto i : axisnames)
axes.push_back(new wx_axes_editor_axis(t_s, this, i));
top_s->Add(t_s);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(okbutton = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
okbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_axes_editor::on_ok), NULL, this);
cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_axes_editor::on_cancel), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
t_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
}
wx_axes_editor::~wx_axes_editor()
{
for(auto i : axes)
delete i;
}
bool wx_axes_editor::ShouldPreventAppExit() const
{
return false;
}
void wx_axes_editor::on_value_change(wxCommandEvent& e)
{
bool all_ok = true;
for(auto i : axes)
all_ok = all_ok && i->is_ok();
okbutton->Enable(all_ok);
}
void wx_axes_editor::on_cancel(wxCommandEvent& e)
{
EndModal(wxID_CANCEL);
}
void wx_axes_editor::on_ok(wxCommandEvent& e)
{
for(auto i : axes)
i->apply();
EndModal(wxID_OK);
}

View file

@ -0,0 +1,41 @@
#ifndef _wxwidgets_axeseditor__hpp__included__
#define _wxwidgets_axeseditor__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include <vector>
#include <string>
class wx_axes_editor_axis
{
public:
wx_axes_editor_axis(wxSizer* sizer, wxWindow* window, const std::string& name);
bool is_ok();
void apply();
private:
std::string a_name;
wxComboBox* a_type;
wxTextCtrl* a_low;
wxTextCtrl* a_mid;
wxTextCtrl* a_high;
wxTextCtrl* a_tolerance;
};
class wx_axes_editor : public wxDialog
{
public:
wx_axes_editor(wxWindow* parent);
~wx_axes_editor();
bool ShouldPreventAppExit() const;
void on_value_change(wxCommandEvent& e);
void on_cancel(wxCommandEvent& e);
void on_ok(wxCommandEvent& e);
private:
std::vector<wx_axes_editor_axis*> axes;
wxButton* okbutton;
wxButton* cancel;
};
#endif

View file

@ -0,0 +1,195 @@
#include "callrom.hpp"
#include "common.hpp"
#define TNAME_SNES "SNES"
#define TNAME_BSX_NS "BS-X (non-slotted)"
#define TNAME_BSX_S "BS-X (slotted)"
#define TNAME_SUFAMITURBO "Sufami Turbo"
#define TNAME_SGB "SGB"
#define RNAME_AUTO "Autodetect"
#define RNAME_NTSC "NTSC"
#define RNAME_PAL "PAL"
#define WNAME_SNES_MAIN "ROM"
#define WNAME_SNES_MAIN_XML "ROM XML"
#define WNAME_BS_MAIN "BS-X BIOS"
#define WNAME_BS_MAIN_XML "BS-X BIOS XML"
#define WNAME_BS_SLOTA "BS FLASH"
#define WNAME_BS_SLOTA_XML "BS FLASH XML"
#define WNAME_ST_MAIN "ST BIOS"
#define WNAME_ST_MAIN_XML "ST BIOS XML"
#define WNAME_ST_SLOTA "SLOT A ROM"
#define WNAME_ST_SLOTA_XML "SLOT A XML"
#define WNAME_ST_SLOTB "SLOT B ROM"
#define WNAME_ST_SLOTB_XML "SLOT B XML"
#define WNAME_SGB_MAIN "SGB BIOS"
#define WNAME_SGB_MAIN_XML "SGB BIOS XML"
#define WNAME_SGB_SLOTA "DMG ROM"
#define WNAME_SGB_SLOTA_XML "BMG XML"
enum rom_type romtype_from_string(const std::string& str)
{
if(str == TNAME_SNES)
return ROMTYPE_SNES;
if(str == TNAME_BSX_NS)
return ROMTYPE_BSX;
if(str == TNAME_BSX_S)
return ROMTYPE_BSXSLOTTED;
if(str == TNAME_SUFAMITURBO)
return ROMTYPE_SUFAMITURBO;
if(str == TNAME_SGB)
return ROMTYPE_SGB;
return ROMTYPE_NONE;
}
enum rom_type romtype_from_string(const wxString& str)
{
return romtype_from_string(tostdstring(str));
}
wxString romname_wxs(enum rom_type rtype, unsigned index)
{
return towxstring(romname_stds(rtype, index));
}
std::string romname_stds(enum rom_type rtype, unsigned index)
{
switch(rtype) {
case ROMTYPE_SNES:
switch(index) {
case 0: return WNAME_SNES_MAIN;
case 1: return WNAME_SNES_MAIN_XML;
};
break;
case ROMTYPE_BSX:
case ROMTYPE_BSXSLOTTED:
switch(index) {
case 0: return WNAME_BS_MAIN;
case 1: return WNAME_BS_MAIN_XML;
case 2: return WNAME_BS_SLOTA;
case 3: return WNAME_BS_SLOTA_XML;
};
break;
case ROMTYPE_SUFAMITURBO:
switch(index) {
case 0: return WNAME_ST_MAIN;
case 1: return WNAME_ST_MAIN_XML;
case 2: return WNAME_ST_SLOTA;
case 3: return WNAME_ST_SLOTA_XML;
case 4: return WNAME_ST_SLOTB;
case 5: return WNAME_ST_SLOTB_XML;
};
break;
case ROMTYPE_SGB:
switch(index) {
case 0: return WNAME_SGB_MAIN;
case 1: return WNAME_SGB_MAIN_XML;
case 2: return WNAME_SGB_SLOTA;
case 3: return WNAME_SGB_SLOTA_XML;
};
break;
case ROMTYPE_NONE:
if(index == 0) return "dummy";
break;
}
return "";
}
unsigned fill_rom_names(enum rom_type rtype, wxString* array)
{
unsigned r = 0;
for(unsigned i = 0; i < 6; i++) {
wxString s = romname_wxs(rtype, i);
if(s.Length())
array[r++] = s;
}
return r;
}
unsigned romname_to_index(enum rom_type rtype, const wxString& name)
{
std::string s = tostdstring(name);
for(unsigned i = 0; i < 6; i++)
if(romname_stds(rtype, i) == s)
return i;
return 6;
}
struct loaded_slot& get_rom_slot(struct loaded_rom& rom, unsigned index)
{
switch(index) {
case 0: return rom.rom;
case 1: return rom.rom_xml;
case 2: return rom.slota;
case 3: return rom.slota_xml;
case 4: return rom.slotb;
case 5: return rom.slotb_xml;
}
return rom.rom;
}
enum rom_region region_from_string(const std::string& str)
{
if(str == RNAME_NTSC)
return REGION_NTSC;
if(str == RNAME_PAL)
return REGION_PAL;
return REGION_AUTO;
}
enum rom_region region_from_string(const wxString& str)
{
return region_from_string(tostdstring(str));
}
bool has_forced_region(enum rom_type rtype)
{
return (rtype != ROMTYPE_SNES && rtype != ROMTYPE_SGB);
}
bool has_forced_region(const std::string& str)
{
return has_forced_region(romtype_from_string(str));
}
bool has_forced_region(const wxString& str)
{
return has_forced_region(romtype_from_string(str));
}
wxString forced_region_for_romtype(enum rom_type rtype)
{
if(has_forced_region(rtype))
return wxT(RNAME_NTSC);
else
return wxT("");
}
wxString forced_region_for_romtype(const std::string& str)
{
return forced_region_for_romtype(romtype_from_string(str));
}
wxString forced_region_for_romtype(const wxString& str)
{
return forced_region_for_romtype(romtype_from_string(str));
}
unsigned populate_region_choices(wxString* array)
{
array[0] = wxT(RNAME_AUTO);
array[1] = wxT(RNAME_NTSC);
array[2] = wxT(RNAME_PAL);
return 3;
}
unsigned populate_system_choices(wxString* array)
{
array[0] = wxT(TNAME_SNES);
array[1] = wxT(TNAME_BSX_NS);
array[2] = wxT(TNAME_BSX_S);
array[3] = wxT(TNAME_SUFAMITURBO);
array[4] = wxT(TNAME_SGB);
return 5;
}

View file

@ -0,0 +1,26 @@
#ifndef _wxwidgets_callrom__hpp__included__
#define _wxwidgets_callrom__hpp__included__
#include "rom.hpp"
#include <wx/string.h>
#include <string>
enum rom_type romtype_from_string(const std::string& str);
enum rom_type romtype_from_string(const wxString& str);
wxString romname_wxs(enum rom_type rtype, unsigned index);
std::string romname_stds(enum rom_type rtype, unsigned index);
unsigned fill_rom_names(enum rom_type rtype, wxString* array);
unsigned romname_to_index(enum rom_type rtype, const wxString& name);
struct loaded_slot& get_rom_slot(struct loaded_rom& rom, unsigned index);
enum rom_region region_from_string(const std::string& str);
enum rom_region region_from_string(const wxString& str);
bool has_forced_region(enum rom_type rtype);
bool has_forced_region(const std::string& str);
bool has_forced_region(const wxString& str);
wxString forced_region_for_romtype(enum rom_type rtype);
wxString forced_region_for_romtype(const std::string& str);
wxString forced_region_for_romtype(const wxString& str);
unsigned populate_region_choices(wxString* array);
unsigned populate_system_choices(wxString* array);
#endif

View file

@ -0,0 +1,17 @@
#include "common.hpp"
wxString towxstring(const std::string& str)
{
return wxString(str.c_str(), wxConvUTF8);
}
std::string tostdstring(const wxString& str)
{
return std::string(str.mb_str(wxConvUTF8));
}
long primary_window_style = wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX;
long secondary_window_style = wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN;
wxFrame* window1;
wxFrame* window2;

View file

@ -0,0 +1,45 @@
#ifndef _wxwidgets_common__hpp__included__
#define _wxwidgets_common__hpp__included__
#include <wx/string.h>
#include <wx/wx.h>
wxString towxstring(const std::string& str);
std::string tostdstring(const wxString& str);
extern long primary_window_style;
extern long secondary_window_style;
typedef wxStaticText* wxStaticText_ptr;
extern wxFrame* window1;
extern wxFrame* window2;
template<class T>
void cmdbutton_action(T* target, wxButton* button, void (T::*fptr)(wxCommandEvent& e))
{
button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction)(wxEventFunction)
static_cast<wxCommandEventFunction>(fptr), NULL, target);
}
template<class T>
void menu_action(T* target, int id, void (T::*fptr)(wxCommandEvent& e))
{
target->Connect(id, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)(wxEventFunction)
static_cast<wxCommandEventFunction>(fptr), NULL, target);
}
template<class T>
void menu_action(T* target, int id, void (T::*fptr)(wxCommandEvent& e), std::string subcmd)
{
target->Connect(id, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)(wxEventFunction)
static_cast<wxCommandEventFunction>(fptr), NULL, target);
}
#define CNAME_NONE "None"
#define CNAME_GAMEPAD "Gamepad"
#define CNAME_MULTITAP "Multitap"
#define CNAME_MOUSE "Mouse"
#define CNAME_SUPERSCOPE "Superscope"
#define CNAME_JUSTIFIER "Justifier"
#define CNAME_JUSTIFIERS "2 Justifiers"
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
#ifndef _wxwdigets_emufn__hpp__included__
#define _wxwdigets_emufn__hpp__included__
#include "rom.hpp"
#include "moviefile.hpp"
void boot_emulator(loaded_rom& rom, moviefile& movie);
void exec_command(const std::string& cmd);
#endif

View file

@ -0,0 +1,138 @@
#include "filenamebox.hpp"
#include "common.hpp"
#include "zip.hpp"
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
filenamebox::filenamebox(wxSizer* sizer, wxWindow* parent, const std::string& initial_label, int flags,
wxEvtHandler* dispatch_to, wxObjectEventFunction on_fn_change)
{
wxSizer* inner = sizer;
if(flags & FNBF_OI)
inner = new wxFlexGridSizer(1, 3, 0, 0);
given_flags = flags;
last_label = initial_label;
label = new wxStaticText(parent, wxID_ANY, towxstring(last_label));
filename = new wxTextCtrl(parent, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(500, -1));
file_select = new wxButton(parent, wxID_ANY, wxT("..."));
inner->Add(label, 0, wxGROW);
inner->Add(filename, 1, wxGROW);
inner->Add(file_select, 0, wxGROW);
if((flags & FNBF_NN) == 0)
filename->Connect(wxEVT_COMMAND_TEXT_UPDATED, on_fn_change, NULL, dispatch_to);
file_select->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(filenamebox::on_file_select), NULL,
this);
if(flags & FNBF_SD)
disable();
if(flags & FNBF_OI) {
inner->SetSizeHints(parent);
sizer->Add(inner, 0, wxGROW);
}
pwindow = parent;
enabled = ((flags & FNBF_SD) == 0);
}
filenamebox::~filenamebox()
{
//Wxwidgets destroys the subwidgets.
}
void filenamebox::on_file_select(wxCommandEvent& e)
{
std::string fname;
wxFileDialog* d = new wxFileDialog(pwindow, towxstring("Choose " + last_label), wxT("."));
if(d->ShowModal() == wxID_CANCEL) {
d->Destroy();
return;
}
fname = tostdstring(d->GetPath());
d->Destroy();
if(given_flags & FNBF_PZ) {
//Did we pick a .zip file?
try {
zip_reader zr(fname);
std::vector<wxString> files;
for(auto i : zr)
files.push_back(towxstring(i));
wxSingleChoiceDialog* d2 = new wxSingleChoiceDialog(pwindow, wxT("Select file within .zip"),
wxT("Select member"), files.size(), &files[0]);
if(d2->ShowModal() == wxID_CANCEL) {
d2->Destroy();
return;
}
fname = fname + "/" + tostdstring(d2->GetStringSelection());
d2->Destroy();
} catch(...) {
//Ignore error.
}
}
filename->SetValue(towxstring(fname));
}
std::string filenamebox::get_file()
{
if(!enabled)
return "";
else
return tostdstring(filename->GetValue());
}
bool filenamebox::is_enabled()
{
return enabled;
}
void filenamebox::enable(const std::string& new_label)
{
change_label(new_label);
enable();
}
void filenamebox::change_label(const std::string& new_label)
{
last_label = new_label;
if(enabled || (given_flags & FNBF_PL))
label->SetLabel(towxstring(last_label));
}
void filenamebox::disable()
{
label->Disable();
filename->Disable();
file_select->Disable();
if((given_flags & FNBF_PL) == 0)
label->SetLabel(wxT(""));
enabled = false;
}
void filenamebox::enable()
{
if((given_flags & FNBF_PL) == 0)
label->SetLabel(towxstring(last_label));
label->Enable();
filename->Enable();
file_select->Enable();
enabled = true;
}
bool filenamebox::is_nonblank()
{
if(!enabled)
return false;
return (filename->GetValue().Length() != 0);
}
bool filenamebox::is_nonblank_or_disabled()
{
if(!enabled)
return true;
return (filename->GetValue().Length() != 0);
}
void filenamebox::clear()
{
filename->SetValue(wxT(""));
}

View file

@ -0,0 +1,44 @@
#ifndef _wxwidgets_filenamebox__hpp__included__
#define _wxwidgets_filenamebox__hpp__included__
//Permanent label.
#define FNBF_PL 1
//Start disabled.
#define FNBF_SD 2
//No notification on filename change.
#define FNBF_NN 4
//Insert as one item.
#define FNBF_OI 8
//Peek inside .zip files.
#define FNBF_PZ 16
#include <wx/wx.h>
#include <wx/event.h>
class filenamebox : public wxEvtHandler
{
public:
filenamebox(wxSizer* sizer, wxWindow* parent, const std::string& initial_label, int flags,
wxEvtHandler* dispatch_to, wxObjectEventFunction on_fn_change);
~filenamebox();
void disable();
void enable();
void change_label(const std::string& new_label);
void enable(const std::string& new_label);
bool is_enabled();
std::string get_file();
void on_file_select(wxCommandEvent& e);
bool is_nonblank();
bool is_nonblank_or_disabled();
void clear();
private:
int given_flags;
std::string last_label;
bool enabled;
wxStaticText* label;
wxTextCtrl* filename;
wxButton* file_select;
wxWindow* pwindow;
};
#endif

View file

@ -0,0 +1,148 @@
#include "keyentry.hpp"
#include "common.hpp"
#include "keymapper.hpp"
#define S_DONT_CARE "Ignore"
#define S_RELEASED "Released"
#define S_PRESSED "Pressed"
wx_key_entry::wx_key_entry(wxWindow* parent)
: wxDialog(parent, wxID_ANY, wxT("Specify key"), wxDefaultPosition, wxSize(-1, -1))
{
std::vector<wxString> keych;
std::set<std::string> mods = modifier::get_set();
std::set<std::string> keys = keygroup::get_keys();
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
SetSizer(top_s);
wxFlexGridSizer* t_s = new wxFlexGridSizer(mods.size() + 1, 3, 0, 0);
for(auto i : mods) {
t_s->Add(new wxStaticText(this, wxID_ANY, towxstring(i)), 0, wxGROW);
keyentry_mod_data m;
t_s->Add(m.pressed = new wxCheckBox(this, wxID_ANY, wxT("Pressed")), 0, wxGROW);
t_s->Add(m.unmasked = new wxCheckBox(this, wxID_ANY, wxT("Unmasked")), 0, wxGROW);
m.pressed->Disable();
modifiers[i] = m;
m.pressed->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
wxCommandEventHandler(wx_key_entry::on_change_setting), NULL, this);
m.unmasked->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
wxCommandEventHandler(wx_key_entry::on_change_setting), NULL, this);
}
for(auto i : keys)
keych.push_back(towxstring(i));
mainkey = new labeledcombobox(t_s, this, "Key", &keych[0], keych.size(), 0, true, this,
(wxObjectEventFunction)(&wx_key_entry::on_change_setting));
t_s->Add(new wxStaticText(this, wxID_ANY, wxT("")), 0, wxGROW);
top_s->Add(t_s);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(ok = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
ok->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_key_entry::on_ok), NULL, this);
cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_key_entry::on_cancel), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
t_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
}
#define TMPFLAG_UNMASKED 65
#define TMPFLAG_UNMASKED_LINK_CHILD 2
#define TMPFLAG_UNMASKED_LINK_PARENT 68
#define TMPFLAG_PRESSED 8
#define TMPFLAG_PRESSED_LINK_CHILD 16
#define TMPFLAG_PRESSED_LINK_PARENT 32
void wx_key_entry::on_change_setting(wxCommandEvent& e)
{
for(auto& i : modifiers)
i.second.tmpflags = 0;
for(auto& i : modifiers) {
modifier* m = NULL;
try {
m = &modifier::lookup(i.first);
} catch(...) {
i.second.pressed->Disable();
i.second.unmasked->Disable();
continue;
}
std::string j = m->linked_name();
if(i.second.unmasked->GetValue())
i.second.tmpflags |= TMPFLAG_UNMASKED;
if(j != "") {
if(modifiers[j].unmasked->GetValue())
i.second.tmpflags |= TMPFLAG_UNMASKED_LINK_PARENT;
if(i.second.unmasked->GetValue())
modifiers[j].tmpflags |= TMPFLAG_UNMASKED_LINK_CHILD;
}
if(i.second.pressed->GetValue())
i.second.tmpflags |= TMPFLAG_PRESSED;
if(j != "") {
if(modifiers[j].pressed->GetValue())
i.second.tmpflags |= TMPFLAG_PRESSED_LINK_PARENT;
if(i.second.pressed->GetValue())
modifiers[j].tmpflags |= TMPFLAG_PRESSED_LINK_CHILD;
}
}
for(auto& i : modifiers) {
//Unmasked is to be enabled if neither unmasked link flag is set.
if(i.second.tmpflags & ((TMPFLAG_UNMASKED_LINK_CHILD | TMPFLAG_UNMASKED_LINK_PARENT) & ~64)) {
i.second.unmasked->SetValue(false);
i.second.unmasked->Disable();
} else
i.second.unmasked->Enable();
//Pressed is to be enabled if:
//- This modifier is unmasked or parent is unmasked.
//- Parent nor child is not pressed.
if(((i.second.tmpflags & (TMPFLAG_UNMASKED | TMPFLAG_UNMASKED_LINK_PARENT | TMPFLAG_PRESSED_LINK_CHILD |
TMPFLAG_PRESSED_LINK_PARENT)) & 112) == 64)
i.second.pressed->Enable();
else {
i.second.pressed->SetValue(false);
i.second.pressed->Disable();
}
}
}
void wx_key_entry::on_ok(wxCommandEvent& e)
{
EndModal(wxID_OK);
}
void wx_key_entry::on_cancel(wxCommandEvent& e)
{
EndModal(wxID_CANCEL);
}
std::string wx_key_entry::getkey()
{
std::string x;
bool f;
f = true;
for(auto i : modifiers) {
if(i.second.pressed->GetValue()) {
if(!f)
x = x + ",";
f = false;
x = x + i.first;
}
}
x = x + "/";
f = true;
for(auto i : modifiers) {
if(i.second.unmasked->GetValue()) {
if(!f)
x = x + ",";
f = false;
x = x + i.first;
}
}
x = x + "|" + mainkey->get_choice();
return x;
}

View file

@ -0,0 +1,35 @@
#ifndef _wxwidgets_keyentry__hpp__included__
#define _wxwidgets_keyentry__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include <vector>
#include <string>
#include "window.hpp"
#include "labelcombobox.hpp"
struct keyentry_mod_data
{
wxCheckBox* pressed;
wxCheckBox* unmasked;
unsigned tmpflags;
};
class wx_key_entry : public wxDialog
{
public:
wx_key_entry(wxWindow* parent);
void on_change_setting(wxCommandEvent& e);
void on_ok(wxCommandEvent& e);
void on_cancel(wxCommandEvent& e);
std::string getkey();
private:
std::map<std::string, keyentry_mod_data> modifiers;
labeledcombobox* mainkey;
wxButton* ok;
wxButton* cancel;
};
#endif

View file

@ -0,0 +1,48 @@
#include "labelcombobox.hpp"
#include "command.hpp"
labeledcombobox::labeledcombobox(wxSizer* sizer, wxWindow* parent, const std::string& label, wxString* choices,
size_t choice_count, size_t defaultidx, bool start_enabled, wxEvtHandler* dispatch_to,
wxObjectEventFunction on_fn_change)
{
sizer->Add(new wxStaticText(parent, wxID_ANY, towxstring(label)), 0, wxGROW);
sizer->Add(combo = new wxComboBox(parent, wxID_ANY, choices[defaultidx], wxDefaultPosition, wxDefaultSize,
choice_count, choices, wxCB_READONLY), 0, wxGROW);
if(dispatch_to)
combo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, on_fn_change, NULL, dispatch_to);
combo->Enable(start_enabled);
enabled = start_enabled;
forced = false;
}
std::string labeledcombobox::get_choice()
{
return tostdstring(combo->GetValue());
}
void labeledcombobox::enable()
{
if(forced && !enabled)
combo->SetValue(remembered);
combo->Enable();
enabled = true;
}
void labeledcombobox::disable(const wxString& choice)
{
combo->Disable();
if(enabled)
remembered = combo->GetValue();
combo->SetValue(choice);
enabled = false;
forced = true;
}
void labeledcombobox::disable()
{
combo->Disable();
if(enabled)
remembered = combo->GetValue();
enabled = false;
forced = false;
}

View file

@ -0,0 +1,31 @@
#ifndef _labelcombobox__hpp__included__
#define _labelcombobox__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include <wx/string.h>
#include "filenamebox.hpp"
#include "common.hpp"
#include <string>
class labeledcombobox
{
public:
labeledcombobox(wxSizer* sizer, wxWindow* parent, const std::string& label, wxString* choices,
size_t choice_count, size_t defaultidx, bool start_enabled, wxEvtHandler* dispatch_to,
wxObjectEventFunction on_fn_change);
std::string get_choice();
void enable();
void disable(const wxString& choice);
void disable();
private:
wxStaticText* label;
wxComboBox* combo;
wxString remembered;
bool enabled;
bool forced;
};
#endif

View file

@ -0,0 +1,143 @@
#include "messages_window.hpp"
#include "window.hpp"
#include "emufn.hpp"
#define MAXMESSAGES 20
class wx_message_panel : public wxPanel
{
public:
wx_message_panel(unsigned lines);
void on_paint(wxPaintEvent& e);
};
wx_messages_window* wx_messages_window::ptr;
wx_message_panel::wx_message_panel(unsigned lines)
: wxPanel(wx_messages_window::ptr)
{
wxMemoryDC d;
wxSize s = d.GetTextExtent(wxT("MMMMMM"));
SetMinSize(wxSize(12 * s.x, lines * s.y));
this->Connect(wxEVT_PAINT, wxPaintEventHandler(wx_message_panel::on_paint), NULL, this);
}
namespace {
wx_message_panel* mpanel;
}
wx_messages_window::wx_messages_window()
: wxFrame(NULL, wxID_ANY, wxT("lsnes: Messages"), wxDefaultPosition, wxSize(-1, -1), secondary_window_style)
{
ptr = this;
wxFlexGridSizer* top_s = new wxFlexGridSizer(3, 1, 0, 0);
top_s->Add(mpanel = new wx_message_panel(MAXMESSAGES));
window::msgbuf.set_max_window_size(MAXMESSAGES);
wxFlexGridSizer* buttons_s = new wxFlexGridSizer(1, 6, 0, 0);
wxButton* beginning, * pageup, * lineup, * linedown, * pagedown, * end;
buttons_s->Add(beginning = new wxButton(this, wxID_ANY, wxT("Beginning")), 1, wxGROW);
buttons_s->Add(pageup = new wxButton(this, wxID_ANY, wxT("Page Up")), 1, wxGROW);
buttons_s->Add(lineup = new wxButton(this, wxID_ANY, wxT("Line Up")), 1, wxGROW);
buttons_s->Add(linedown = new wxButton(this, wxID_ANY, wxT("Line Down")), 1, wxGROW);
buttons_s->Add(pagedown = new wxButton(this, wxID_ANY, wxT("Page Down")), 1, wxGROW);
buttons_s->Add(end = new wxButton(this, wxID_ANY, wxT("End")), 1, wxGROW);
beginning->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_home),
NULL, this);
pageup->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_pageup),
NULL, this);
lineup->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_lineup),
NULL, this);
linedown->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_linedown),
NULL, this);
pagedown->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_pagedown),
NULL, this);
end->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_scroll_end),
NULL, this);
top_s->Add(buttons_s, 0, wxGROW);
wxBoxSizer* cmd_s = new wxBoxSizer(wxHORIZONTAL);
wxButton* execute;
cmd_s->Add(command = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER), 1, wxEXPAND);
cmd_s->Add(execute = new wxButton(this, wxID_ANY, wxT("Execute")), 0, wxGROW);
command->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(wx_messages_window::on_execute),
NULL, this);
execute->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wx_messages_window::on_execute),
NULL, this);
cmd_s->SetSizeHints(this);
top_s->Add(cmd_s, 0, wxGROW);
top_s->SetSizeHints(this);
SetSizer(top_s);
Fit();
}
wx_messages_window::~wx_messages_window()
{
ptr = NULL;
}
void wx_message_panel::on_paint(wxPaintEvent& e)
{
wxPaintDC dc(this);
dc.Clear();
int y = 0;
size_t lines = window::msgbuf.get_visible_count();
size_t first = window::msgbuf.get_visible_first();
for(size_t i = 0; i < lines; i++) {
wxSize s = dc.GetTextExtent(towxstring(window::msgbuf.get_message(first + i)));
dc.DrawText(towxstring(window::msgbuf.get_message(first + i)), 0, y);
y += s.y;
}
}
void wx_messages_window::on_scroll_home(wxCommandEvent& e)
{
window::msgbuf.scroll_beginning();
}
void wx_messages_window::on_scroll_pageup(wxCommandEvent& e)
{
window::msgbuf.scroll_up_page();
}
void wx_messages_window::on_scroll_lineup(wxCommandEvent& e)
{
window::msgbuf.scroll_up_line();
}
void wx_messages_window::on_scroll_linedown(wxCommandEvent& e)
{
window::msgbuf.scroll_down_line();
}
void wx_messages_window::on_scroll_pagedown(wxCommandEvent& e)
{
window::msgbuf.scroll_down_page();
}
void wx_messages_window::on_scroll_end(wxCommandEvent& e)
{
window::msgbuf.scroll_end();
}
void wx_messages_window::on_execute(wxCommandEvent& e)
{
std::string cmd = tostdstring(command->GetValue());
if(cmd == "")
return;
exec_command(cmd);
}
void wx_messages_window::notify_message()
{
mpanel->Refresh();
}
bool wx_messages_window::ShouldPreventAppExit() const
{
return false;
}

View file

@ -0,0 +1,30 @@
#ifndef _wxwidgets_messages_window__hpp__included__
#define _wxwidgets_messages_window__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include "filenamebox.hpp"
#include "common.hpp"
class wx_messages_window : public wxFrame
{
public:
wx_messages_window();
~wx_messages_window();
bool ShouldPreventAppExit() const;
static wx_messages_window* ptr;
void notify_message();
void on_scroll_home(wxCommandEvent& e);
void on_scroll_pageup(wxCommandEvent& e);
void on_scroll_lineup(wxCommandEvent& e);
void on_scroll_linedown(wxCommandEvent& e);
void on_scroll_pagedown(wxCommandEvent& e);
void on_scroll_end(wxCommandEvent& e);
void on_execute(wxCommandEvent& e);
private:
wxTextCtrl* command;
};
#endif

View file

@ -0,0 +1,252 @@
#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;
}

View file

@ -0,0 +1,43 @@
#ifndef _wxwidgets_project_select_window__hpp__included__
#define _wxwidgets_project_select_window__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include "filenamebox.hpp"
#include "rom.hpp"
#include "moviefile.hpp"
#include "labelcombobox.hpp"
#include <set>
#include <map>
#include <string>
class wx_project_select_window : public wxFrame
{
public:
wx_project_select_window(loaded_rom& rom);
~wx_project_select_window();
void on_file_select(wxCommandEvent& e);
void on_new_select(wxCommandEvent& e);
void on_filename_change(wxCommandEvent& e);
void on_quit(wxCommandEvent& e);
void on_load(wxCommandEvent& e);
loaded_rom* our_rom;
private:
bool load_file;
std::set<std::string> get_sram_set();
struct moviefile make_movie();
filenamebox* filename;
std::map<std::string, filenamebox*> srams;
labeledcombobox* controller1type;
labeledcombobox* controller2type;
wxTextCtrl* projectname;
wxTextCtrl* rtc_sec;
wxTextCtrl* rtc_subsec;
wxTextCtrl* authors;
wxButton* load;
wxButton* quit;
};
#endif

View file

@ -0,0 +1,159 @@
#include "lsnes.hpp"
#include <snes/snes.hpp>
#include <ui-libsnes/libsnes.hpp>
#include "rom_patch_window.hpp"
#include "project_select_window.hpp"
#include "callrom.hpp"
#include "zip.hpp"
#include "framerate.hpp"
namespace
{
class my_interfaced : public SNES::Interface
{
string path(SNES::Cartridge::Slot slot, const string &hint)
{
return "./";
}
} simple_interface;
}
wx_rom_patch_window::wx_rom_patch_window(loaded_rom& rom)
: wxFrame(NULL, wxID_ANY, wxT("Patch ROM"), wxDefaultPosition, wxSize(-1, -1),
primary_window_style)
{
our_rom = &rom;
size_t target_count = fill_rom_names(rom.rtype, targets);
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(5, 1, 0, 0);
SetSizer(top_s);
wxFlexGridSizer* checksums_s = new wxFlexGridSizer(target_count, 2, 0, 0);
for(unsigned i = 0; i < 6; i++)
checksums[i] = NULL;
for(unsigned i = 0; i < target_count; i++) {
checksums_s->Add(new wxStaticText(this, wxID_ANY, targets[i]), 0, wxGROW);
checksums_s->Add(checksums[i] = new wxStaticText(this, wxID_ANY,
towxstring(get_rom_slot(*our_rom, i).sha256)), 0, wxGROW);
}
top_s->Add(checksums_s, 0, wxGROW);
wxFlexGridSizer* pwhat_s = new wxFlexGridSizer(1, 2, 0, 0);
pwhat_s->Add(new wxStaticText(this, wxID_ANY, wxT("Patch what:")), 0, wxGROW);
pwhat_s->Add(patch_what = new wxComboBox(this, wxID_ANY, targets[0], wxDefaultPosition, wxDefaultSize,
target_count, targets, wxCB_READONLY), 0, wxGROW);
top_s->Add(pwhat_s, 0, wxGROW);
patchfile = new filenamebox(top_s, this, "Patch file", FNBF_PL | FNBF_OI | FNBF_PZ, this,
wxCommandEventHandler(wx_rom_patch_window::on_patchfile_change));
wxFlexGridSizer* poffset_s = new wxFlexGridSizer(1, 2, 0, 0);
pwhat_s->Add(new wxStaticText(this, wxID_ANY, wxT("Patch offset:")), 0, wxGROW);
pwhat_s->Add(patch_offset = new wxTextCtrl(this, wxID_ANY, wxT("")), 0, wxGROW);
patch_offset->Connect(wxEVT_COMMAND_TEXT_UPDATED,
wxCommandEventHandler(wx_rom_patch_window::on_patchfile_change), NULL, this);
top_s->Add(poffset_s, 0, wxGROW);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
wxButton* thats_enough = new wxButton(this, wxID_ANY, wxT("Enough"));
pbutton_s->Add(thats_enough, 0, wxGROW);
thats_enough->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_rom_patch_window::on_done), NULL, this);
dopatch = new wxButton(this, wxID_ANY, wxT("Patch"));
pbutton_s->Add(dopatch, 0, wxGROW);
dopatch->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_rom_patch_window::on_do_patch), NULL, this);
dopatch->Disable();
wxButton* quitbutton = new wxButton(this, wxID_EXIT, wxT("Quit"));
pbutton_s->Add(quitbutton, 0, wxGROW);
quitbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_rom_patch_window::on_quit), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
patch_offset->SetValue(wxT("0"));
checksums_s->SetSizeHints(this);
pwhat_s->SetSizeHints(this);
pbutton_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
}
wx_rom_patch_window::~wx_rom_patch_window()
{
delete patchfile;
}
void wx_rom_patch_window::on_patchfile_change(wxCommandEvent& e)
{
//std::cerr << "wx_rom_patch_window::on_patchfile_change" << std::endl;
bool ok = true;
//std::cerr << "wx_rom_patch_window::on_patchfile_change: #1: ok=" << ok << std::endl;
ok = ok && patchfile->is_nonblank();
//std::cerr << "wx_rom_patch_window::on_patchfile_change: #2: ok=" << ok << std::endl;
std::string offsetv = tostdstring(patch_offset->GetValue());
try {
int32_t offset = boost::lexical_cast<int32_t>(offsetv);
} catch(...) {
ok = false;
}
//std::cerr << "wx_rom_patch_window::on_patchfile_change: #3: ok=" << ok << std::endl;
if(dopatch) {
//std::cerr << "wx_rom_patch_window::on_patchfile_change: #4: ok=" << ok << std::endl;
dopatch->Enable(ok);
}
//std::cerr << "wx_rom_patch_window::on_patchfile_change: #5: ok=" << ok << std::endl;
}
void wx_rom_patch_window::on_do_patch(wxCommandEvent& e)
{
try {
auto patch_contents = read_file_relative(patchfile->get_file(), "");
size_t patch_index = romname_to_index(our_rom->rtype, patch_what->GetValue());
if(patch_index == 6)
throw std::runtime_error("Internal error: Patch WHAT?");
loaded_slot& s = get_rom_slot(*our_rom, patch_index);
std::string offsetv = tostdstring(patch_offset->GetValue());
int32_t offset = boost::lexical_cast<int32_t>(offsetv);
s.patch(patch_contents, offset);
checksums[patch_index]->SetLabel(towxstring(s.sha256));
} catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
wxT("Error patching ROM"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
return;
}
patchfile->clear();
}
void wx_rom_patch_window::on_quit(wxCommandEvent& e)
{
Close(true);
}
void wx_rom_patch_window::on_done(wxCommandEvent& e)
{
try {
SNES::interface = &simple_interface;
our_rom->load();
} catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
wxT("Error loading ROM"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
return;
}
messages << "Detected region: " << gtype::tostring(our_rom->rtype, our_rom->region) << std::endl;
if(our_rom->region == REGION_PAL)
set_nominal_framerate(322445.0/6448.0);
else if(our_rom->region == REGION_NTSC)
set_nominal_framerate(10738636.0/178683.0);
messages << "--- Internal memory mappings ---" << std::endl;
dump_region_map();
messages << "--- End of Startup --- " << std::endl;
wx_project_select_window* projwin = new wx_project_select_window(*our_rom);
projwin->Show();
Destroy();
}

View file

@ -0,0 +1,31 @@
#ifndef _wxwidgets_rom_patch_window__hpp__included__
#define _wxwidgets_rom_patch_window__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include "filenamebox.hpp"
#include "rom.hpp"
#include "common.hpp"
class wx_rom_patch_window : public wxFrame
{
public:
wx_rom_patch_window(loaded_rom& rom);
~wx_rom_patch_window();
void on_patchfile_change(wxCommandEvent& e);
void on_do_patch(wxCommandEvent& e);
void on_quit(wxCommandEvent& e);
void on_done(wxCommandEvent& e);
loaded_rom* our_rom;
private:
filenamebox* patchfile;
wxComboBox* patch_what;
wxButton* dopatch;
wxTextCtrl* patch_offset;
wxStaticText_ptr checksums[6];
wxString targets[6];
};
#endif

View file

@ -0,0 +1,139 @@
#include "rom_select_window.hpp"
#include "rom_patch_window.hpp"
#include "callrom.hpp"
wx_rom_select_window::wx_rom_select_window()
: wxFrame(NULL, wxID_ANY, wxT("Select ROM"), wxDefaultPosition, wxSize(-1, -1),
primary_window_style)
{
wxString rtchoices[5];
wxString rrchoices[3];
size_t systems = populate_system_choices(rtchoices);
size_t regions = populate_region_choices(rrchoices);
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(3, 1, 0, 0);
SetSizer(top_s);
wxBoxSizer* selects_s = new wxBoxSizer(wxHORIZONTAL);
rtypec = new labeledcombobox(selects_s, this, "ROM type:", rtchoices, systems, 0, true, this,
wxCommandEventHandler(wx_rom_select_window::on_romtype_change));
regionc = new labeledcombobox(selects_s, this, "Region:", rrchoices, regions, 0, true, this,
wxCommandEventHandler(wx_rom_select_window::on_romtype_change));
top_s->Add(selects_s, 0, wxGROW);
//The XMLs don't matter, so don't notify those.
wxFlexGridSizer* romgrid_s = new wxFlexGridSizer(6, 3, 0, 0);
main_rom = new filenamebox(romgrid_s, this, "ROM", FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
main_xml = new filenamebox(romgrid_s, this, "ROM XML", FNBF_NN | FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
slota_rom = new filenamebox(romgrid_s, this, "SLOT A ROM", FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
slota_xml = new filenamebox(romgrid_s, this, "SLOT A XML", FNBF_NN | FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
slotb_rom = new filenamebox(romgrid_s, this, "SLOT A ROM", FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
slotb_xml = new filenamebox(romgrid_s, this, "SLOT A XML", FNBF_NN | FNBF_PZ, this,
wxCommandEventHandler(wx_rom_select_window::on_filename_change));
top_s->Add(romgrid_s, 1, wxGROW);
wxBoxSizer* button_s = new wxBoxSizer(wxHORIZONTAL);
button_s->AddStretchSpacer();
button_s->Add(open_rom = new wxButton(this, wxID_OPEN, wxT("Open ROM")), 0, wxALIGN_RIGHT);
button_s->Add(quit_button = new wxButton(this, wxID_EXIT, wxT("Quit")), 0, wxALIGN_RIGHT);
open_rom->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_rom_select_window::on_open_rom), NULL, this);
open_rom->Disable();
quit_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_rom_select_window::on_quit), NULL, this);
top_s->Add(button_s, 1, wxGROW);
set_rtype("");
top_s->SetSizeHints(this);
Fit();
}
wx_rom_select_window::~wx_rom_select_window()
{
delete rtypec;
delete regionc;
delete main_rom;
delete main_xml;
delete slota_rom;
delete slota_xml;
delete slotb_rom;
delete slotb_xml;
}
void wx_rom_select_window::set_rtype(std::string rtype)
{
bool no_rtype = (current_rtype == "");
if(rtype == "")
rtype = rtypec->get_choice();
if(rtype == current_rtype)
return;
if(has_forced_region(rtype))
regionc->disable(forced_region_for_romtype(rtype));
else
regionc->enable();
wxString tmp[6];
unsigned c = fill_rom_names(romtype_from_string(rtype), tmp);
if(c > 0) main_rom->enable(tostdstring(tmp[0])); else main_rom->disable();
if(c > 1) main_xml->enable(tostdstring(tmp[1])); else main_xml->disable();
if(c > 2) slota_rom->enable(tostdstring(tmp[2])); else slota_rom->disable();
if(c > 3) slota_xml->enable(tostdstring(tmp[3])); else slota_xml->disable();
if(c > 4) slotb_rom->enable(tostdstring(tmp[4])); else slotb_rom->disable();
if(c > 5) slotb_xml->enable(tostdstring(tmp[5])); else slotb_xml->disable();
current_rtype = rtype;
Fit();
}
void wx_rom_select_window::on_filename_change(wxCommandEvent& e)
{
bool ok = true;
enum rom_type rtype = romtype_from_string(rtypec->get_choice());
ok = ok && main_rom->is_nonblank();
if(rtype == ROMTYPE_BSX || rtype == ROMTYPE_BSXSLOTTED || rtype == ROMTYPE_SGB)
ok = ok && slota_rom->is_nonblank();
if(rtype == ROMTYPE_SUFAMITURBO)
ok = ok && (slota_rom->is_nonblank() || slotb_rom->is_nonblank());
open_rom->Enable(ok);
}
void wx_rom_select_window::on_romtype_change(wxCommandEvent& e)
{
set_rtype(rtypec->get_choice());
on_filename_change(e);
}
void wx_rom_select_window::on_quit(wxCommandEvent& e)
{
Close(true);
}
void wx_rom_select_window::on_open_rom(wxCommandEvent& e)
{
rom_files rfiles;
rfiles.base_file = "";
rfiles.rtype = romtype_from_string(rtypec->get_choice());
rfiles.region = region_from_string(regionc->get_choice());
rfiles.rom = main_rom->get_file();
rfiles.rom_xml = main_xml->get_file();
rfiles.slota = slota_rom->get_file();
rfiles.slota_xml = slota_xml->get_file();
rfiles.slotb = slotb_rom->get_file();
rfiles.slotb_xml = slotb_xml->get_file();
try {
our_rom = new loaded_rom(rfiles);
} catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(this, towxstring(e.what()),
wxT("Error loading ROM"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
}
wx_rom_patch_window* projwin = new wx_rom_patch_window(*our_rom);
projwin->Show();
Destroy();
}

View file

@ -0,0 +1,37 @@
#ifndef _wxwidgets_rom_select_window__hpp__included__
#define _wxwidgets_rom_select_window__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include "filenamebox.hpp"
#include "rom.hpp"
#include "labelcombobox.hpp"
class wx_rom_select_window : public wxFrame
{
public:
wx_rom_select_window();
~wx_rom_select_window();
void on_filename_change(wxCommandEvent& e);
void on_romtype_change(wxCommandEvent& e);
void on_quit(wxCommandEvent& e);
void on_open_rom(wxCommandEvent& e);
loaded_rom* our_rom;
private:
labeledcombobox* rtypec;
labeledcombobox* regionc;
filenamebox* main_rom;
filenamebox* main_xml;
filenamebox* slota_rom;
filenamebox* slota_xml;
filenamebox* slotb_rom;
filenamebox* slotb_xml;
wxButton* open_rom;
wxButton* quit_button;
std::string current_rtype;
void set_rtype(std::string rtype);
};
#endif

View file

@ -0,0 +1,147 @@
#include "settingseditor.hpp"
#include "settings.hpp"
#include "common.hpp"
#include "window.hpp"
#include <stdexcept>
wx_settings_editor_setting::wx_settings_editor_setting(wxSizer* sizer, wxWindow* window, const std::string& name)
{
a_name = name;
parent = window;
std::string pvalue = "<unknown>";
try {
if(!setting::is_set(a_name))
pvalue = "<unset>";
else
pvalue = setting::get(a_name);
} catch(...) {
}
sizer->Add(new wxStaticText(window, wxID_ANY, towxstring(name)), 0, wxGROW);
sizer->Add(label = new wxStaticText(window, wxID_ANY, towxstring(pvalue)), 0, wxGROW);
sizer->Add(edit = new wxButton(window, wxID_ANY, wxT("Edit")), 0, wxGROW);
sizer->Add(clear = new wxButton(window, wxID_ANY, wxT("Clear")), 0, wxGROW);
edit->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_settings_editor_setting::on_edit_click), NULL, this);
clear->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_settings_editor_setting::on_clear_click), NULL, this);
}
void wx_settings_editor_setting::on_clear_click(wxCommandEvent& e)
{
try {
setting::blank(a_name);
}catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(parent, towxstring(std::string("Can't clear setting: ") +
e.what()), wxT("Error"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
d->Destroy();
}
}
void wx_settings_editor_setting::on_edit_click(wxCommandEvent& e)
{
try {
std::string newsetting;
std::string oldvalue = setting::get(a_name);
wxTextEntryDialog* d = new wxTextEntryDialog(parent, towxstring("Enter new value for " + a_name),
wxT("Enter new value for setting"), towxstring(oldvalue));
if(d->ShowModal() == wxID_CANCEL) {
d->Destroy();
return;
}
newsetting = tostdstring(d->GetValue());
setting::set(a_name, newsetting);
} catch(std::exception& e) {
wxMessageDialog* d = new wxMessageDialog(parent, towxstring(std::string("Can't set setting: ") +
e.what()), wxT("Error"), wxOK | wxICON_EXCLAMATION);
d->ShowModal();
d->Destroy();
}
}
void wx_settings_editor_setting::change_setting(const std::string& _setting, const std::string& value)
{
if(_setting != a_name)
return;
label->SetLabel(towxstring(value));
}
void wx_settings_editor_setting::clear_setting(const std::string& _setting)
{
if(_setting != a_name)
return;
label->SetLabel(wxT("<unset>"));
}
wx_settings_editor::wx_settings_editor(wxWindow* parent)
: wxDialog(parent, wxID_ANY, wxT("lsnes: Edit settings"), wxDefaultPosition, wxSize(-1, -1)), listener(this)
{
std::set<std::string> settings_set = setting::get_settings_set();
Centre();
wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
SetSizer(top_s);
wxFlexGridSizer* t_s = new wxFlexGridSizer(settings_set.size(), 4, 0, 0);
for(auto i : settings_set)
esettings.push_back(new wx_settings_editor_setting(t_s, this, i));
top_s->Add(t_s);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(close = new wxButton(this, wxID_CANCEL, wxT("Close")), 0, wxGROW);
close->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wx_settings_editor::on_close), NULL, this);
top_s->Add(pbutton_s, 0, wxGROW);
t_s->SetSizeHints(this);
top_s->SetSizeHints(this);
Fit();
}
wx_settings_editor::~wx_settings_editor()
{
for(auto i : esettings)
delete i;
}
bool wx_settings_editor::ShouldPreventAppExit() const
{
return false;
}
void wx_settings_editor::on_close(wxCommandEvent& e)
{
EndModal(wxID_OK);
}
void wx_settings_editor::change_setting(const std::string& _setting, const std::string& value)
{
for(auto i : esettings)
i->change_setting(_setting, value);
}
void wx_settings_editor::clear_setting(const std::string& _setting)
{
for(auto i : esettings)
i->clear_setting(_setting);
}
wx_settings_editor_listener::wx_settings_editor_listener(wx_settings_editor* _editor)
{
editor = _editor;
}
wx_settings_editor_listener::~wx_settings_editor_listener() throw()
{
}
void wx_settings_editor_listener::on_setting_change(const std::string& _setting, const std::string& value)
{
editor->change_setting(_setting, value);
}
void wx_settings_editor_listener::on_setting_clear(const std::string& _setting)
{
editor->clear_setting(_setting);
}

View file

@ -0,0 +1,56 @@
#ifndef _wxwidgets_settingseditor__hpp__included__
#define _wxwidgets_settingseditor__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include <vector>
#include <string>
#include "window.hpp"
class wx_settings_editor_setting : public wxEvtHandler
{
public:
wx_settings_editor_setting(wxSizer* sizer, wxWindow* window, const std::string& name);
void on_clear_click(wxCommandEvent& e);
void on_edit_click(wxCommandEvent& e);
void change_setting(const std::string& setting, const std::string& value);
void clear_setting(const std::string& setting);
private:
std::string a_name;
wxWindow* parent;
wxStaticText* label;
wxButton* clear;
wxButton* edit;
};
class wx_settings_editor;
class wx_settings_editor_listener : public window_callback
{
public:
wx_settings_editor_listener(wx_settings_editor* _editor);
~wx_settings_editor_listener() throw();
void on_setting_change(const std::string& setting, const std::string& value);
void on_setting_clear(const std::string& setting);
private:
wx_settings_editor* editor;
};
class wx_settings_editor : public wxDialog
{
public:
wx_settings_editor(wxWindow* parent);
~wx_settings_editor();
bool ShouldPreventAppExit() const;
void on_close(wxCommandEvent& e);
void change_setting(const std::string& setting, const std::string& value);
void clear_setting(const std::string& setting);
private:
wx_settings_editor_listener listener;
std::vector<wx_settings_editor_setting*> esettings;
wxButton* close;
};
#endif

View file

@ -0,0 +1,75 @@
#include "status_window.hpp"
#include "window.hpp"
#include "emufn.hpp"
#define MAXSTATUS 30
class wx_status_panel : public wxPanel
{
public:
wx_status_panel(unsigned lines);
void on_paint(wxPaintEvent& e);
bool dirty;
};
wx_status_window* wx_status_window::ptr;
wx_status_panel::wx_status_panel(unsigned lines)
: wxPanel(wx_status_window::ptr)
{
dirty = false;
wxMemoryDC d;
wxSize s = d.GetTextExtent(wxT("MMMMMM"));
SetMinSize(wxSize(6 * s.x, lines * s.y));
this->Connect(wxEVT_PAINT, wxPaintEventHandler(wx_status_panel::on_paint), NULL, this);
}
namespace {
wx_status_panel* spanel;
}
wx_status_window::wx_status_window()
: wxFrame(NULL, wxID_ANY, wxT("lsnes: Status"), wxDefaultPosition, wxSize(-1, -1), secondary_window_style)
{
ptr = this;
wxFlexGridSizer* top_s = new wxFlexGridSizer(1, 1, 0, 0);
top_s->Add(spanel = new wx_status_panel(MAXSTATUS));
top_s->SetSizeHints(this);
SetSizer(top_s);
Fit();
}
wx_status_window::~wx_status_window()
{
ptr = NULL;
}
void wx_status_panel::on_paint(wxPaintEvent& e)
{
wxPaintDC dc(this);
dc.Clear();
int y = 0;
auto& status = window::get_emustatus();
for(auto i : status) {
std::string pstr = i.first + ": " + i.second;
wxSize s = dc.GetTextExtent(towxstring(pstr));
dc.DrawText(towxstring(pstr), 0, y);
y += s.y;
}
dirty = false;
}
void wx_status_window::notify_status_change()
{
if(!spanel || spanel->dirty)
return;
spanel->dirty = true;
spanel->Refresh();
}
bool wx_status_window::ShouldPreventAppExit() const
{
return false;
}

View file

@ -0,0 +1,24 @@
#ifndef _wxwidgets_status_window__hpp__included__
#define _wxwidgets_status_window__hpp__included__
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/control.h>
#include <wx/combobox.h>
#include "common.hpp"
#include <map>
#include <string>
class wx_status_window : public wxFrame
{
public:
wx_status_window();
~wx_status_window();
bool ShouldPreventAppExit() const;
static wx_status_window* ptr;
void notify_status_change();
};
void repaint_status_window();
#endif