Update to v070r06 release.

(there was no r05 release posted to the WIP thread)

byuu says:

- bsnes/phoenix uses XML for per-game cheat codes, markup is identical
  to the main database
- added clear and clear all buttons to the cheat code editor
- phoenix/GTK+ sets all child menu elements to match the parent menu font
- phoenix/Windows will draw a black canvas for the Viewport widget
  (phoenix/GTK+ still needs this)
This commit is contained in:
Tim Allen
2010-10-03 19:17:11 +11:00
parent 775c111fef
commit 96e9333ec2
15 changed files with 175 additions and 68 deletions

View File

@@ -64,7 +64,7 @@ ifeq ($(platform),x)
install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes
install -D -m 644 ui-qt/data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png install -D -m 644 ui-qt/data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 ui-qt/data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop install -D -m 644 ui-qt/data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
gconftool-2 --type bool --set /desktop/gnome/interface/menus_have_icons true # gconftool-2 --type bool --set /desktop/gnome/interface/menus_have_icons true
endif endif
uninstall: uninstall:

View File

@@ -8,13 +8,14 @@ namespace nall {
struct container { struct container {
virtual R operator()(P... p) const = 0; virtual R operator()(P... p) const = 0;
virtual container* copy() const = 0; virtual container* copy() const = 0;
virtual ~container() {}
} *callback; } *callback;
struct global : container { struct global : container {
R (*function)(P...); R (*function)(P...);
R operator()(P... p) const { return function(std::forward<P>(p)...); } R operator()(P... p) const { return function(std::forward<P>(p)...); }
container* copy() const { return new global(function); } container* copy() const { return new global(function); }
global(R (*function_)(P...)) : function(function_) {} global(R (*function)(P...)) : function(function) {}
}; };
template<typename C> struct member : container { template<typename C> struct member : container {
@@ -22,15 +23,14 @@ namespace nall {
C *object; C *object;
R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); } R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); }
container* copy() const { return new member(function, object); } container* copy() const { return new member(function, object); }
member(R (C::*function_)(P...), C *object_) : function(function_), object(object_) {} member(R (C::*function)(P...), C *object) : function(function), object(object) {}
}; };
template<typename L> struct lambda : container { template<typename L> struct lambda : container {
L *object; L object;
R operator()(P... p) const { return (*object)(std::forward<P>(p)...); } R operator()(P... p) const { return object(std::forward<P>(p)...); }
container* copy() const { return new lambda(*object); } container* copy() const { return new lambda(object); }
lambda(const L& object_) { object = new L(object_); } lambda(const L& object) : object(object) {}
~lambda() { delete object; }
}; };
public: public:
@@ -38,8 +38,10 @@ namespace nall {
R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); } R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); }
function& operator=(const function &source) { function& operator=(const function &source) {
if(callback) { delete callback; callback = 0; } if(this != &source) {
if(source.callback) callback = source.callback->copy(); if(callback) { delete callback; callback = 0; }
if(source.callback) callback = source.callback->copy();
}
return *this; return *this;
} }

View File

@@ -75,10 +75,11 @@ inline string xml_element::parse() const {
if(strbegin(source, "<![CDATA[")) { if(strbegin(source, "<![CDATA[")) {
if(auto pos = strpos(source, "]]>")) { if(auto pos = strpos(source, "]]>")) {
string cdata = substr(source, 9, pos() - 9); if(pos() - 9 > 0) {
data << cdata; string cdata = substr(source, 9, pos() - 9);
offset += strlen(cdata); data << cdata;
offset += strlen(cdata);
}
source += 9 + offset + 3; source += 9 + offset + 3;
continue; continue;
} else { } else {

View File

@@ -30,11 +30,14 @@ inline Font::Style operator|(Font::Style a, Font::Style b) { return (Font::Style
inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); } inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); }
struct Action : Object { struct Action : Object {
void setFont(Font &font);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
Action();
//private:
struct Data;
Data *action;
}; };
struct Menu : Action { struct Menu : Action {

View File

@@ -1,14 +1,12 @@
static void Action_setFont(GtkWidget *widget, gpointer font) { static void Action_setFont(GtkWidget *widget, gpointer font) {
gtk_widget_modify_font(widget, (PangoFontDescription*)font); if(font) {
if(GTK_IS_CONTAINER(widget)) { gtk_widget_modify_font(widget, (PangoFontDescription*)font);
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Action_setFont, font); if(GTK_IS_CONTAINER(widget)) {
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Action_setFont, (PangoFontDescription*)font);
}
} }
} }
void Action::setFont(Font &font) {
Action_setFont(object->widget, font.font->font);
}
bool Action::visible() { bool Action::visible() {
return gtk_widget_get_visible(object->widget); return gtk_widget_get_visible(object->widget);
} }
@@ -25,25 +23,35 @@ void Action::setEnabled(bool enabled) {
gtk_widget_set_sensitive(object->widget, enabled); gtk_widget_set_sensitive(object->widget, enabled);
} }
Action::Action() {
action = new Action::Data;
action->font = 0;
}
void Menu::create(Window &parent, const char *text) { void Menu::create(Window &parent, const char *text) {
action->font = parent.window->defaultFont;
object->menu = gtk_menu_new(); object->menu = gtk_menu_new();
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_bar_append(parent.object->menu, object->widget); gtk_menu_bar_append(parent.object->menu, object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void Menu::create(Menu &parent, const char *text) { void Menu::create(Menu &parent, const char *text) {
action->font = parent.action->font;
object->menu = gtk_menu_new(); object->menu = gtk_menu_new();
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void MenuSeparator::create(Menu &parent) { void MenuSeparator::create(Menu &parent) {
action->font = parent.action->font;
object->widget = gtk_separator_menu_item_new(); object->widget = gtk_separator_menu_item_new();
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -53,8 +61,10 @@ static void MenuItem_tick(MenuItem *self) {
} }
void MenuItem::create(Menu &parent, const char *text) { void MenuItem::create(Menu &parent, const char *text) {
action->font = parent.action->font;
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(MenuItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(MenuItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -64,8 +74,10 @@ static void MenuCheckItem_tick(MenuCheckItem *self) {
} }
void MenuCheckItem::create(Menu &parent, const char *text) { void MenuCheckItem::create(Menu &parent, const char *text) {
action->font = parent.action->font;
object->widget = gtk_check_menu_item_new_with_label(text); object->widget = gtk_check_menu_item_new_with_label(text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuCheckItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuCheckItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -86,18 +98,22 @@ static void MenuRadioItem_tick(MenuRadioItem *self) {
void MenuRadioItem::create(Menu &parent, const char *text) { void MenuRadioItem::create(Menu &parent, const char *text) {
first = this; first = this;
action->font = parent.action->font;
object->parentMenu = &parent; object->parentMenu = &parent;
object->widget = gtk_radio_menu_item_new_with_label(0, text); object->widget = gtk_radio_menu_item_new_with_label(0, text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void MenuRadioItem::create(MenuRadioItem &parent, const char *text) { void MenuRadioItem::create(MenuRadioItem &parent, const char *text) {
first = parent.first; first = parent.first;
action->font = parent.action->font;
object->parentMenu = parent.object->parentMenu; object->parentMenu = parent.object->parentMenu;
object->widget = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(first->object->widget), text); object->widget = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(first->object->widget), text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(object->parentMenu->object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(object->parentMenu->object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }

View File

@@ -17,6 +17,10 @@ struct Font::Data {
PangoFontDescription *font; PangoFontDescription *font;
}; };
struct Action::Data {
Font *font;
};
struct Widget::Data { struct Widget::Data {
Window *parent; Window *parent;
}; };

View File

@@ -3,6 +3,14 @@ void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, un
widget->parent = &parent; widget->parent = &parent;
gtk_widget_set_double_buffered(object->widget, false); gtk_widget_set_double_buffered(object->widget, false);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
GdkColor color;
color.pixel = 0;
color.red = 0;
color.green = 0;
color.blue = 0;
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }

View File

@@ -1,7 +1,7 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "070.04"; static const char Version[] = "070.06";
static const unsigned SerializerVersion = 13; static const unsigned SerializerVersion = 13;
} }
} }

View File

@@ -4,7 +4,7 @@ ui_objects += $(if $(call streq,$(platform),win),resource)
# platform # platform
ifeq ($(platform),x) ifeq ($(platform),x)
flags += -DPHOENIX_GTK `pkg-config --cflags gtk+-2.0` phoenix_compile = $(call compile,-DPHOENIX_GTK `pkg-config --cflags gtk+-2.0`)
link += `pkg-config --libs gtk+-2.0` link += `pkg-config --libs gtk+-2.0`
# flags += -DPHOENIX_QT `pkg-config --cflags QtCore QtGui` # flags += -DPHOENIX_QT `pkg-config --cflags QtCore QtGui`
# link += `pkg-config --libs QtCore QtGui` # link += `pkg-config --libs QtCore QtGui`
@@ -15,13 +15,16 @@ ifeq ($(platform),x)
link += $(if $(findstring audio.openal,$(ruby)),-lopenal) link += $(if $(findstring audio.openal,$(ruby)),-lopenal)
else ifeq ($(platform),osx) else ifeq ($(platform),osx)
phoenix_compile = $(call compile,-DPHOENIX_QT)
link +=
ruby := ruby :=
ruby += audio.openal ruby += audio.openal
ruby += input.carbon ruby += input.carbon
link += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL) link += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
else ifeq ($(platform),win) else ifeq ($(platform),win)
flags += -DPHOENIX_WINDOWS phoenix_compile = $(call compile,-DPHOENIX_WINDOWS)
link += link +=
ruby := video.direct3d video.wgl video.directdraw video.gdi ruby := video.direct3d video.wgl video.directdraw video.gdi
@@ -54,18 +57,19 @@ rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
# rules # rules
objects := $(ui_objects) $(objects) objects := $(ui_objects) $(objects)
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/*) obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/*); $(phoenix_compile)
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/general/*) obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/general/*); $(phoenix_compile)
obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/tools/*) obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/tools/*); $(phoenix_compile)
obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/settings/*) obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/settings/*); $(phoenix_compile)
obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/input/*) obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/input/*); $(phoenix_compile)
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/utility/*) obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/utility/*); $(phoenix_compile)
obj/ui-cartridge.o: $(ui)/cartridge/cartridge.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/cartridge/*) obj/ui-cartridge.o: $(ui)/cartridge/cartridge.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/cartridge/*); $(phoenix_compile)
obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/*) obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/*)
$(call compile,$(rubydef) $(rubyflags)) $(call compile,$(rubydef) $(rubyflags))
obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/*) obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/*)
$(phoenix_compile)
obj/resource.o: $(ui)/resource.rc obj/resource.o: $(ui)/resource.rc
windres $(ui)/resource.rc obj/resource.o windres $(ui)/resource.rc obj/resource.o

View File

@@ -22,8 +22,8 @@ void Configuration::create() {
attach(video.region = 0, "video.region"); attach(video.region = 0, "video.region");
attach(video.scale = 2, "video.scale"); attach(video.scale = 2, "video.scale");
attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection"); attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection");
attach(video.contrast = 100, "video.contrast");
attach(video.brightness = 100, "video.brightness"); attach(video.brightness = 100, "video.brightness");
attach(video.contrast = 100, "video.contrast");
attach(video.gamma = 100, "video.gamma"); attach(video.gamma = 100, "video.gamma");
attach(video.useGammaRamp = true, "video.useGammaRamp"); attach(video.useGammaRamp = true, "video.useGammaRamp");

View File

@@ -16,8 +16,8 @@ struct Configuration : public configuration {
bool region; bool region;
unsigned scale; unsigned scale;
bool aspectRatioCorrection; bool aspectRatioCorrection;
unsigned contrast;
unsigned brightness; unsigned brightness;
unsigned contrast;
unsigned gamma; unsigned gamma;
bool useGammaRamp; bool useGammaRamp;
} video; } video;

View File

@@ -10,14 +10,14 @@ void VideoSettings::create() {
colorAdjustmentLabel.create(*this, x, y, 430, Style::LabelHeight, "Color Adjustment :."); y += Style::LabelHeight + 5; colorAdjustmentLabel.create(*this, x, y, 430, Style::LabelHeight, "Color Adjustment :."); y += Style::LabelHeight + 5;
colorAdjustmentLabel.setFont(application.proportionalFontBold); colorAdjustmentLabel.setFont(application.proportionalFontBold);
contrastLabel.create (*this, x, y, 80, Style::SliderHeight, "Contrast:");
contrastValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%");
contrastSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight;
brightnessLabel.create (*this, x, y, 80, Style::SliderHeight, "Brightness:"); brightnessLabel.create (*this, x, y, 80, Style::SliderHeight, "Brightness:");
brightnessValue.create (*this, x + 80, y, 40, Style::SliderHeight, "100%"); brightnessValue.create (*this, x + 80, y, 40, Style::SliderHeight, "100%");
brightnessSlider.create(*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight; brightnessSlider.create(*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight;
contrastLabel.create (*this, x, y, 80, Style::SliderHeight, "Contrast:");
contrastValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%");
contrastSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight;
gammaLabel.create (*this, x, y, 80, Style::SliderHeight, "Gamma:"); gammaLabel.create (*this, x, y, 80, Style::SliderHeight, "Gamma:");
gammaValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%"); gammaValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%");
gammaSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5; gammaSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5;
@@ -35,8 +35,8 @@ void VideoSettings::create() {
setGeometry(160, 160, 440, y); setGeometry(160, 160, 440, y);
contrastSlider.setPosition(config.video.contrast);
brightnessSlider.setPosition(config.video.brightness); brightnessSlider.setPosition(config.video.brightness);
contrastSlider.setPosition(config.video.contrast);
gammaSlider.setPosition(config.video.gamma); gammaSlider.setPosition(config.video.gamma);
gammaRampCheck.setChecked(config.video.useGammaRamp); gammaRampCheck.setChecked(config.video.useGammaRamp);
@@ -59,12 +59,12 @@ void VideoSettings::create() {
} }
void VideoSettings::adjust() { void VideoSettings::adjust() {
contrastValue.setText(string(contrastSlider.position(), "%"));
brightnessValue.setText(string(brightnessSlider.position(), "%")); brightnessValue.setText(string(brightnessSlider.position(), "%"));
contrastValue.setText(string(contrastSlider.position(), "%"));
gammaValue.setText(string(gammaSlider.position(), "%")); gammaValue.setText(string(gammaSlider.position(), "%"));
config.video.contrast = contrastSlider.position();
config.video.brightness = brightnessSlider.position(); config.video.brightness = brightnessSlider.position();
config.video.contrast = contrastSlider.position();
config.video.gamma = gammaSlider.position(); config.video.gamma = gammaSlider.position();
config.video.useGammaRamp = gammaRampCheck.checked(); config.video.useGammaRamp = gammaRampCheck.checked();
palette.update(); palette.update();

View File

@@ -1,11 +1,11 @@
struct VideoSettings : Window { struct VideoSettings : Window {
Label colorAdjustmentLabel; Label colorAdjustmentLabel;
Label contrastLabel;
Label contrastValue;
HorizontalSlider contrastSlider;
Label brightnessLabel; Label brightnessLabel;
Label brightnessValue; Label brightnessValue;
HorizontalSlider brightnessSlider; HorizontalSlider brightnessSlider;
Label contrastLabel;
Label contrastValue;
HorizontalSlider contrastSlider;
Label gammaLabel; Label gammaLabel;
Label gammaValue; Label gammaValue;
HorizontalSlider gammaSlider; HorizontalSlider gammaSlider;

View File

@@ -11,41 +11,68 @@ void CheatEditor::load(string filename) {
cheatText[i][3] = ""; cheatText[i][3] = "";
} }
unsigned n = 0;
string data; string data;
if(data.readfile(string(filename, ".bsv"))) { data.readfile(string(filename, ".cht"));
lstring list; xml_element document = xml_parse(data);
list.split("\n", data); foreach(head, document.element) {
for(unsigned i = 0; i < 128 && i < list.size(); i++) { if(head.name == "cartridge") {
lstring part; foreach(node, head.element) {
part.split("{}", list[i]); if(node.name == "cheat") {
cheatText[i][1] = part[0]; bool enabled = false;
cheatText[i][2] = part[1]; string description;
cheatText[i][3] = part[2]; string code;
SNES::cheat[i].enabled = (cheatText[i][1] != " "); foreach(attribute, node.attribute) {
SNES::cheat[i] = cheatText[i][2]; if(attribute.name == "enabled") enabled = (attribute.parse() == "true");
}
foreach(element, node.element) {
if(element.name == "description") description = element.parse();
else if(element.name == "code") code.append(string(element.parse(), "+"));
}
code.rtrim("+");
SNES::cheat[n].enabled = enabled;
SNES::cheat[n] = code;
cheatText[n][1] = (enabled == false ? " " : "*");
cheatText[n][2] = code;
cheatText[n][3] = description;
if(++n >= 128) break;
}
}
} }
} }
refresh(); refresh();
synchronize();
} }
void CheatEditor::save(string filename) { void CheatEditor::save(string filename) {
bool savesPresent = false; signed lastSave = -1;
for(unsigned i = 0; i < 128; i++) { for(signed i = 127; i >= 0; i--) {
if(cheatText[i][2] != "" || cheatText[i][3] != "") { if(cheatText[i][2] != "" || cheatText[i][3] != "") {
savesPresent = true; lastSave = i;
break; break;
} }
} }
if(savesPresent == false) { if(lastSave == -1) {
unlink(string(filename, ".bsv")); unlink(string(filename, ".cht"));
return; return;
} }
file fp; file fp;
if(fp.open(string(filename, ".bsv"), file::mode_write)) { if(fp.open(string(filename, ".cht"), file::mode_write)) {
for(unsigned i = 0; i < 128; i++) { fp.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fp.print(string(cheatText[i][1], "{}", cheatText[i][2], "{}", cheatText[i][3], "\n")); fp.print(string("<cartridge sha256=\"", SNES::cartridge.sha256(), "\">\n"));
for(unsigned i = 0; i <= lastSave; i++) {
fp.print(string(" <cheat enabled=\"", cheatText[i][1] == " " ? "false" : "true", "\">\n"));
fp.print(string(" <description><![CDATA[", cheatText[i][3], "]]></description>\n"));
lstring list;
list.split("+", cheatText[i][2]);
foreach(code, list) {
fp.print(string(" <code>", code, "</code>\n"));
}
fp.print(string(" </cheat>\n"));
} }
fp.print("</cartridge>\n");
fp.close(); fp.close();
} }
@@ -58,9 +85,9 @@ void CheatEditor::create() {
Window::create(0, 0, 256, 256, "Cheat Editor"); Window::create(0, 0, 256, 256, "Cheat Editor");
setDefaultFont(application.proportionalFont); setDefaultFont(application.proportionalFont);
unsigned x = 5, y = 5; unsigned x = 5, y = 5, height = Style::ButtonHeight;
cheatList.create(*this, x, y, 500, 250, "Slot\tOn\tCode\tDescription"); y += 255; cheatList.create(*this, x, y, 500, 250, "Slot\tCode\tDescription"); y += 255;
cheatList.setHeaderVisible(); cheatList.setHeaderVisible();
codeLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Code(s):"); codeLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Code(s):");
@@ -69,25 +96,33 @@ void CheatEditor::create() {
descLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Description:"); descLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Description:");
descEdit.create (*this, x + 80, y, 420, Style::TextBoxHeight); y+= Style::TextBoxHeight + 5; descEdit.create (*this, x + 80, y, 420, Style::TextBoxHeight); y+= Style::TextBoxHeight + 5;
clearAllButton.create(*this, x + 505 - 85 - 85, y, 80, height, "Clear All");
clearButton.create(*this, x + 505 - 85, y, 80, height, "Clear"); y += height + 5;
setGeometry(160, 160, 510, y); setGeometry(160, 160, 510, y);
synchronize(); synchronize();
cheatList.onActivate = { &CheatEditor::toggle, this }; cheatList.onActivate = { &CheatEditor::toggle, this };
cheatList.onChange = { &CheatEditor::synchronize, this }; cheatList.onChange = { &CheatEditor::synchronize, this };
codeEdit.onChange = descEdit.onChange = { &CheatEditor::bind, this }; codeEdit.onChange = descEdit.onChange = { &CheatEditor::bind, this };
clearAllButton.onTick = { &CheatEditor::clearAll, this };
clearButton.onTick = { &CheatEditor::clear, this };
} }
void CheatEditor::synchronize() { void CheatEditor::synchronize() {
clearAllButton.setEnabled(SNES::cartridge.loaded());
if(auto position = cheatList.selection()) { if(auto position = cheatList.selection()) {
codeEdit.setText(cheatText[position()][2]); codeEdit.setText(cheatText[position()][2]);
descEdit.setText(cheatText[position()][3]); descEdit.setText(cheatText[position()][3]);
codeEdit.setEnabled(true); codeEdit.setEnabled(true);
descEdit.setEnabled(true); descEdit.setEnabled(true);
clearButton.setEnabled(true);
} else { } else {
codeEdit.setText(""); codeEdit.setText("");
descEdit.setText(""); descEdit.setText("");
codeEdit.setEnabled(false); codeEdit.setEnabled(false);
descEdit.setEnabled(false); descEdit.setEnabled(false);
clearButton.setEnabled(false);
} }
} }
@@ -100,7 +135,7 @@ void CheatEditor::refresh() {
if(list.size() > 1) cheatCode.append("..."); if(list.size() > 1) cheatCode.append("...");
cheatList.setItem(i, string( cheatList.setItem(i, string(
cheatText[i][0], "\t", cheatText[i][1], "\t", cheatCode, "\t", cheatText[i][3] cheatText[i][0], cheatText[i][1], "\t", cheatCode, "\t", cheatText[i][3]
)); ));
} }
cheatList.resizeColumnsToContent(); cheatList.resizeColumnsToContent();
@@ -109,7 +144,7 @@ void CheatEditor::refresh() {
void CheatEditor::toggle() { void CheatEditor::toggle() {
if(auto position = cheatList.selection()) { if(auto position = cheatList.selection()) {
if(cheatText[position()][1] == " ") { if(cheatText[position()][1] == " ") {
cheatText[position()][1] = "X"; cheatText[position()][1] = "*";
SNES::cheat[position()].enabled = true; SNES::cheat[position()].enabled = true;
} else { } else {
cheatText[position()][1] = " "; cheatText[position()][1] = " ";
@@ -127,3 +162,33 @@ void CheatEditor::bind() {
refresh(); refresh();
} }
} }
void CheatEditor::clearAll() {
if(MessageWindow::question(cheatEditor, "Permanently erase all entered cheat codes?", MessageWindow::Buttons::YesNo) == MessageWindow::Response::Yes) {
for(unsigned i = 0; i < 128; i++) {
SNES::cheat[i].enabled = false;
SNES::cheat[i] = "";
cheatText[i][1] = " ";
cheatText[i][2] = "";
cheatText[i][3] = "";
}
SNES::cheat.synchronize();
refresh();
codeEdit.setText("");
descEdit.setText("");
}
}
void CheatEditor::clear() {
if(auto position = cheatList.selection()) {
SNES::cheat[position()].enabled = false;
SNES::cheat[position()] = "";
cheatText[position()][1] = " ";
cheatText[position()][2] = "";
cheatText[position()][3] = "";
SNES::cheat.synchronize();
refresh();
codeEdit.setText("");
descEdit.setText("");
}
}

View File

@@ -4,6 +4,8 @@ struct CheatEditor : Window {
TextBox codeEdit; TextBox codeEdit;
Label descLabel; Label descLabel;
TextBox descEdit; TextBox descEdit;
Button clearAllButton;
Button clearButton;
void load(string filename); void load(string filename);
void save(string filename); void save(string filename);
@@ -15,6 +17,8 @@ private:
void refresh(); void refresh();
void toggle(); void toggle();
void bind(); void bind();
void clearAll();
void clear();
}; };
extern CheatEditor cheatEditor; extern CheatEditor cheatEditor;