From da5263bfc3088ded5e18eca11a2746aa91071415 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 28 Sep 2010 00:38:32 +1000 Subject: [PATCH] Update to v070r01 release. byuu says: - phoenix supports onActivate, or return key pressed, on text boxes - phoenix supports setGeometry() on all widgets - input settings can now map analog axes and analog buttons - analog button support is simplified over bsnes/Qt, and it supports the trigger inversion you see between Xbox 360 and Thrustmaster controllers - load cartridge window lets you press enter in the path box to select the folder, but currently allows invalid folders (makes list empty) - load cartridge won't reset your view if the folder doesn't change - this means the last ROM you loaded is highlighted the next time you go to load cartridge; you're welcome, FitzRoy :P - removed quit system menu option - added dummy controller port system menu options, there's no code behind them yet - added power/reset menu options, dropped the power checkbox in favor of a standard power cycle option, removes unnecessary complexity - added video mode scaling, 1x to 5x; and aspect ratio correction - added video mode smooth toggle - added audio settings panel with volume and input frequency adjustment - config file is where you can control output frequency and latency, they are too niche for a GUI - fixed a realpath() crash on Linux when the bsnes binary was in /usr/bin --- bsnes/Makefile | 4 +- bsnes/nall/Makefile | 4 +- bsnes/phoenix/gtk/button.cpp | 1 + bsnes/phoenix/gtk/canvas.cpp | 1 + bsnes/phoenix/gtk/checkbox.cpp | 1 + bsnes/phoenix/gtk/combobox.cpp | 1 + bsnes/phoenix/gtk/editbox.cpp | 1 + bsnes/phoenix/gtk/gtk.hpp | 6 ++ bsnes/phoenix/gtk/horizontalslider.cpp | 1 + bsnes/phoenix/gtk/label.cpp | 1 + bsnes/phoenix/gtk/listbox.cpp | 1 + bsnes/phoenix/gtk/object.cpp | 4 ++ bsnes/phoenix/gtk/progressbar.cpp | 1 + bsnes/phoenix/gtk/radiobox.cpp | 1 + bsnes/phoenix/gtk/textbox.cpp | 6 ++ bsnes/phoenix/gtk/verticalslider.cpp | 1 + bsnes/phoenix/gtk/viewport.cpp | 1 + bsnes/phoenix/gtk/widget.cpp | 11 ++++ bsnes/phoenix/qt/combobox.cpp | 2 + bsnes/phoenix/qt/qt.hpp | 1 + bsnes/phoenix/qt/qt.moc | 12 ++-- bsnes/phoenix/qt/qt.moc.hpp | 6 +- bsnes/phoenix/qt/textbox.cpp | 1 + bsnes/phoenix/windows/widget.cpp | 4 ++ bsnes/phoenix/windows/windows.cpp | 15 +++-- bsnes/phoenix/windows/windows.hpp | 2 + bsnes/snes/snes.hpp | 2 +- bsnes/ui-phoenix/cartridge/cartridge.cpp | 8 +-- bsnes/ui-phoenix/config.cpp | 7 +++ bsnes/ui-phoenix/config.hpp | 7 +++ bsnes/ui-phoenix/general/file-browser.cpp | 7 ++- bsnes/ui-phoenix/general/main-window.cpp | 72 +++++++++++++++++++++-- bsnes/ui-phoenix/general/main-window.hpp | 22 ++++++- bsnes/ui-phoenix/input/input.cpp | 8 +++ bsnes/ui-phoenix/input/input.hpp | 3 +- bsnes/ui-phoenix/main.cpp | 19 +++--- bsnes/ui-phoenix/settings/audio.cpp | 33 +++++++++++ bsnes/ui-phoenix/settings/audio.hpp | 12 ++++ bsnes/ui-phoenix/settings/input.cpp | 35 ++++++++++- bsnes/ui-phoenix/settings/input.hpp | 6 ++ bsnes/ui-phoenix/settings/settings.cpp | 1 + bsnes/ui-phoenix/settings/settings.hpp | 1 + bsnes/ui-phoenix/settings/video.cpp | 4 +- bsnes/ui-phoenix/utility/utility.cpp | 38 +++++++++++- bsnes/ui-phoenix/utility/utility.hpp | 8 ++- 45 files changed, 340 insertions(+), 43 deletions(-) create mode 100755 bsnes/ui-phoenix/settings/audio.cpp create mode 100755 bsnes/ui-phoenix/settings/audio.hpp diff --git a/bsnes/Makefile b/bsnes/Makefile index ce7eab57..1b055011 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,7 +1,7 @@ include nall/Makefile snes := snes -profile := compatibility -ui := ui-qt +profile := performance +ui := ui-phoenix # compiler c := $(compiler) -std=gnu99 diff --git a/bsnes/nall/Makefile b/bsnes/nall/Makefile index 63fd71ae..9a93bd23 100755 --- a/bsnes/nall/Makefile +++ b/bsnes/nall/Makefile @@ -32,9 +32,9 @@ ifeq ($(compiler),) ifeq ($(platform),win) compiler := gcc else ifeq ($(platform),osx) - compiler := gcc-mp-4.4 + compiler := gcc-mp-4.5 else - compiler := gcc + compiler := gcc-4.5 endif endif diff --git a/bsnes/phoenix/gtk/button.cpp b/bsnes/phoenix/gtk/button.cpp index 5ef019ca..19746a84 100755 --- a/bsnes/phoenix/gtk/button.cpp +++ b/bsnes/phoenix/gtk/button.cpp @@ -4,6 +4,7 @@ static void Button_tick(Button *self) { void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_button_new_with_label(text); + widget->parent = &parent; gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "clicked", G_CALLBACK(Button_tick), (gpointer)this); if(parent.window->defaultFont) setFont(*parent.window->defaultFont); diff --git a/bsnes/phoenix/gtk/canvas.cpp b/bsnes/phoenix/gtk/canvas.cpp index b3889318..43913871 100755 --- a/bsnes/phoenix/gtk/canvas.cpp +++ b/bsnes/phoenix/gtk/canvas.cpp @@ -22,6 +22,7 @@ void Canvas::create(Window &parent, unsigned x, unsigned y, unsigned width, unsi canvas->pitch = width * sizeof(uint32_t); object->widget = gtk_drawing_area_new(); + widget->parent = &parent; GdkColor color; color.pixel = color.red = color.green = color.blue = 0; gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color); diff --git a/bsnes/phoenix/gtk/checkbox.cpp b/bsnes/phoenix/gtk/checkbox.cpp index a424368e..ea1c0cd2 100755 --- a/bsnes/phoenix/gtk/checkbox.cpp +++ b/bsnes/phoenix/gtk/checkbox.cpp @@ -4,6 +4,7 @@ static void CheckBox_tick(CheckBox *self) { void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_check_button_new_with_label(text); + widget->parent = &parent; gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)this); if(parent.window->defaultFont) setFont(*parent.window->defaultFont); diff --git a/bsnes/phoenix/gtk/combobox.cpp b/bsnes/phoenix/gtk/combobox.cpp index 8650dd21..c27e67f5 100755 --- a/bsnes/phoenix/gtk/combobox.cpp +++ b/bsnes/phoenix/gtk/combobox.cpp @@ -4,6 +4,7 @@ void ComboBox_change(ComboBox *self) { void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_combo_box_new_text(); + widget->parent = &parent; gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(ComboBox_change), (gpointer)this); diff --git a/bsnes/phoenix/gtk/editbox.cpp b/bsnes/phoenix/gtk/editbox.cpp index 34dc0eef..ed0d329e 100755 --- a/bsnes/phoenix/gtk/editbox.cpp +++ b/bsnes/phoenix/gtk/editbox.cpp @@ -4,6 +4,7 @@ static void EditBox_change(EditBox *self) { void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_scrolled_window_new(0, 0); + widget->parent = &parent; gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN); gtk_widget_set_size_request(object->widget, width, height); diff --git a/bsnes/phoenix/gtk/gtk.hpp b/bsnes/phoenix/gtk/gtk.hpp index a3facdf1..e491b701 100755 --- a/bsnes/phoenix/gtk/gtk.hpp +++ b/bsnes/phoenix/gtk/gtk.hpp @@ -76,6 +76,11 @@ struct Widget : Object { void setEnabled(bool enabled = true); virtual bool focused(); virtual void setFocused(); + virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); + Widget(); +//private: + struct Data; + Data *widget; }; struct Window : Widget { @@ -190,6 +195,7 @@ private: }; struct TextBox : Widget { + nall::function onActivate; nall::function onChange; void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void setEditable(bool editable = true); diff --git a/bsnes/phoenix/gtk/horizontalslider.cpp b/bsnes/phoenix/gtk/horizontalslider.cpp index 46ee1774..9e6e76c7 100755 --- a/bsnes/phoenix/gtk/horizontalslider.cpp +++ b/bsnes/phoenix/gtk/horizontalslider.cpp @@ -8,6 +8,7 @@ void HorizontalSlider::create(Window &parent, unsigned x, unsigned y, unsigned w object->position = 0; length += (length == 0); object->widget = gtk_hscale_new_with_range(0, length - 1, 1); + widget->parent = &parent; gtk_scale_set_draw_value(GTK_SCALE(object->widget), false); gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)this); diff --git a/bsnes/phoenix/gtk/label.cpp b/bsnes/phoenix/gtk/label.cpp index a5beedd5..9068a9d8 100755 --- a/bsnes/phoenix/gtk/label.cpp +++ b/bsnes/phoenix/gtk/label.cpp @@ -1,5 +1,6 @@ void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_label_new(text); + widget->parent = &parent; gtk_misc_set_alignment(GTK_MISC(object->widget), 0.0, 0.5); gtk_widget_set_size_request(object->widget, width, height); if(parent.window->defaultFont) setFont(*parent.window->defaultFont); diff --git a/bsnes/phoenix/gtk/listbox.cpp b/bsnes/phoenix/gtk/listbox.cpp index 8668e8f8..ab04fc7a 100755 --- a/bsnes/phoenix/gtk/listbox.cpp +++ b/bsnes/phoenix/gtk/listbox.cpp @@ -16,6 +16,7 @@ static void ListBox_activate(ListBox *self) { void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { listBox->selection = -1; object->widget = gtk_scrolled_window_new(0, 0); + widget->parent = &parent; gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN); gtk_widget_set_size_request(object->widget, width, height); diff --git a/bsnes/phoenix/gtk/object.cpp b/bsnes/phoenix/gtk/object.cpp index 11abb7f3..2a3f8e1e 100755 --- a/bsnes/phoenix/gtk/object.cpp +++ b/bsnes/phoenix/gtk/object.cpp @@ -17,6 +17,10 @@ struct Font::Data { PangoFontDescription *font; }; +struct Widget::Data { + Window *parent; +}; + struct Window::Data { Font *defaultFont; }; diff --git a/bsnes/phoenix/gtk/progressbar.cpp b/bsnes/phoenix/gtk/progressbar.cpp index 14e928bf..28af161e 100755 --- a/bsnes/phoenix/gtk/progressbar.cpp +++ b/bsnes/phoenix/gtk/progressbar.cpp @@ -1,5 +1,6 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { object->widget = gtk_progress_bar_new(); + widget->parent = &parent; gtk_widget_set_size_request(object->widget, width, height); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); gtk_widget_show(object->widget); diff --git a/bsnes/phoenix/gtk/radiobox.cpp b/bsnes/phoenix/gtk/radiobox.cpp index 1ec9a556..66ef262f 100755 --- a/bsnes/phoenix/gtk/radiobox.cpp +++ b/bsnes/phoenix/gtk/radiobox.cpp @@ -6,6 +6,7 @@ void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un first = this; object->parentWindow = &parent; object->widget = gtk_radio_button_new_with_label(0, text); + widget->parent = &parent; gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)this); if(parent.window->defaultFont) setFont(*parent.window->defaultFont); diff --git a/bsnes/phoenix/gtk/textbox.cpp b/bsnes/phoenix/gtk/textbox.cpp index f6ea00dc..dbd77966 100755 --- a/bsnes/phoenix/gtk/textbox.cpp +++ b/bsnes/phoenix/gtk/textbox.cpp @@ -1,11 +1,17 @@ +static void TextBox_activate(TextBox *self) { + if(self->onActivate) self->onActivate(); +} + static void TextBox_change(TextBox *self) { if(self->object->locked == false && self->onChange) self->onChange(); } void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { object->widget = gtk_entry_new(); + widget->parent = &parent; gtk_entry_set_text(GTK_ENTRY(object->widget), text); gtk_widget_set_size_request(object->widget, width, height); + g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(TextBox_activate), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(TextBox_change), (gpointer)this); if(parent.window->defaultFont) setFont(*parent.window->defaultFont); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); diff --git a/bsnes/phoenix/gtk/verticalslider.cpp b/bsnes/phoenix/gtk/verticalslider.cpp index 8b0074c2..1cca9e4c 100755 --- a/bsnes/phoenix/gtk/verticalslider.cpp +++ b/bsnes/phoenix/gtk/verticalslider.cpp @@ -8,6 +8,7 @@ void VerticalSlider::create(Window &parent, unsigned x, unsigned y, unsigned wid object->position = 0; length += (length == 0); object->widget = gtk_vscale_new_with_range(0, length - 1, 1); + widget->parent = &parent; gtk_scale_set_draw_value(GTK_SCALE(object->widget), false); gtk_widget_set_size_request(object->widget, width, height); g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)this); diff --git a/bsnes/phoenix/gtk/viewport.cpp b/bsnes/phoenix/gtk/viewport.cpp index 1a0d71ce..49fc1d0e 100755 --- a/bsnes/phoenix/gtk/viewport.cpp +++ b/bsnes/phoenix/gtk/viewport.cpp @@ -1,5 +1,6 @@ void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { object->widget = gtk_drawing_area_new(); + widget->parent = &parent; gtk_widget_set_double_buffered(object->widget, false); gtk_widget_set_size_request(object->widget, width, height); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); diff --git a/bsnes/phoenix/gtk/widget.cpp b/bsnes/phoenix/gtk/widget.cpp index 4e5f73fa..4f0bf079 100755 --- a/bsnes/phoenix/gtk/widget.cpp +++ b/bsnes/phoenix/gtk/widget.cpp @@ -34,3 +34,14 @@ void Widget::setFocused() { if(visible() == false) setVisible(true); gtk_widget_grab_focus(object->widget); } + +void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { + if(widget->parent == 0) return; + gtk_fixed_move(GTK_FIXED(widget->parent->object->formContainer), object->widget, x, y); + gtk_widget_set_size_request(object->widget, width, height); +} + +Widget::Widget() { + widget = new Widget::Data; + widget->parent = 0; +} diff --git a/bsnes/phoenix/qt/combobox.cpp b/bsnes/phoenix/qt/combobox.cpp index 8b951d77..0e65e2c6 100755 --- a/bsnes/phoenix/qt/combobox.cpp +++ b/bsnes/phoenix/qt/combobox.cpp @@ -27,7 +27,9 @@ unsigned ComboBox::selection() { } void ComboBox::setSelection(unsigned row) { + object->locked = true; comboBox->setCurrentIndex(row); + object->locked = false; } ComboBox::ComboBox() { diff --git a/bsnes/phoenix/qt/qt.hpp b/bsnes/phoenix/qt/qt.hpp index e3e240e9..1777dbb8 100755 --- a/bsnes/phoenix/qt/qt.hpp +++ b/bsnes/phoenix/qt/qt.hpp @@ -255,6 +255,7 @@ struct RadioBox : Widget { }; struct TextBox : Widget { + nall::function onActivate; nall::function onChange; void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void setEditable(bool editable = true); diff --git a/bsnes/phoenix/qt/qt.moc b/bsnes/phoenix/qt/qt.moc index ce1b6754..2603198f 100755 --- a/bsnes/phoenix/qt/qt.moc +++ b/bsnes/phoenix/qt/qt.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'qt.moc.hpp' ** -** Created: Sat Sep 25 06:31:14 2010 +** Created: Mon Sep 27 04:00:47 2010 ** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) ** ** WARNING! All changes made in this file will be lost! @@ -761,7 +761,7 @@ static const uint qt_meta_data_TextBox__Data[] = { 4, // revision 0, // classname 0, 0, // classinfo - 1, 14, // methods + 2, 14, // methods 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors @@ -770,12 +770,13 @@ static const uint qt_meta_data_TextBox__Data[] = { // slots: signature, parameters, type, tag, flags 15, 14, 14, 14, 0x0a, + 28, 14, 14, 14, 0x0a, 0 // eod }; static const char qt_meta_stringdata_TextBox__Data[] = { - "TextBox::Data\0\0onChange()\0" + "TextBox::Data\0\0onActivate()\0onChange()\0" }; const QMetaObject TextBox::Data::staticMetaObject = { @@ -807,10 +808,11 @@ int TextBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { - case 0: onChange(); break; + case 0: onActivate(); break; + case 1: onChange(); break; default: ; } - _id -= 1; + _id -= 2; } return _id; } diff --git a/bsnes/phoenix/qt/qt.moc.hpp b/bsnes/phoenix/qt/qt.moc.hpp index 21aa1984..522196a9 100755 --- a/bsnes/phoenix/qt/qt.moc.hpp +++ b/bsnes/phoenix/qt/qt.moc.hpp @@ -164,7 +164,7 @@ public: public slots: void onChange() { - if(self.onChange) self.onChange(); + if(self.object->locked == false && self.onChange) self.onChange(); } }; @@ -262,6 +262,10 @@ public: } public slots: + void onActivate() { + if(self.onActivate) self.onActivate(); + } + void onChange() { if(self.onChange) self.onChange(); } diff --git a/bsnes/phoenix/qt/textbox.cpp b/bsnes/phoenix/qt/textbox.cpp index b1c44a11..aad30066 100755 --- a/bsnes/phoenix/qt/textbox.cpp +++ b/bsnes/phoenix/qt/textbox.cpp @@ -4,6 +4,7 @@ void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns textBox->setText(text); if(parent.window->defaultFont) textBox->setFont(*parent.window->defaultFont); textBox->show(); + textBox->connect(textBox, SIGNAL(returnPressed()), SLOT(onActivate())); textBox->connect(textBox, SIGNAL(textEdited(const QString&)), SLOT(onChange())); } diff --git a/bsnes/phoenix/windows/widget.cpp b/bsnes/phoenix/windows/widget.cpp index 62f3cf77..1741a9b5 100755 --- a/bsnes/phoenix/windows/widget.cpp +++ b/bsnes/phoenix/windows/widget.cpp @@ -28,6 +28,10 @@ void Widget::setFocused() { SetFocus(widget->window); } +void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { + SetWindowPos(widget->window, NULL, x, y, width, height, SWP_NOZORDER); +} + Widget::Widget() { os.objects.append(this); widget = new Widget::Data; diff --git a/bsnes/phoenix/windows/windows.cpp b/bsnes/phoenix/windows/windows.cpp index 4623ca07..4a266d93 100755 --- a/bsnes/phoenix/windows/windows.cpp +++ b/bsnes/phoenix/windows/windows.cpp @@ -211,10 +211,17 @@ static void OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(GetCurrentThreadId(), &info); Object *object_ptr = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA); - if(object_ptr && dynamic_cast(object_ptr)) { - ListBox &listBox = (ListBox&)*object_ptr; - if(wparam == VK_RETURN) { - if(listBox.onActivate) listBox.onActivate(); + if(object_ptr) { + if(dynamic_cast(object_ptr)) { + ListBox &listBox = (ListBox&)*object_ptr; + if(wparam == VK_RETURN) { + if(listBox.onActivate) listBox.onActivate(); + } + } else if(dynamic_cast(object_ptr)) { + TextBox &textBox = (TextBox&)*object_ptr; + if(wparam == VK_RETURN) { + if(textBox.onActivate) textBox.onActivate(); + } } } } diff --git a/bsnes/phoenix/windows/windows.hpp b/bsnes/phoenix/windows/windows.hpp index 1cb4bc56..3b589a9b 100755 --- a/bsnes/phoenix/windows/windows.hpp +++ b/bsnes/phoenix/windows/windows.hpp @@ -84,6 +84,7 @@ struct Widget : Object { void setEnabled(bool enabled = true); bool focused(); void setFocused(); + virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); Widget(); //private: struct Data; @@ -211,6 +212,7 @@ struct RadioBox : Widget { }; struct TextBox : Widget { + nall::function onActivate; nall::function onChange; void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); nall::string text(); diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 6d53e69c..e2599734 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "070"; + static const char Version[] = "070.01"; static const unsigned SerializerVersion = 13; } } diff --git a/bsnes/ui-phoenix/cartridge/cartridge.cpp b/bsnes/ui-phoenix/cartridge/cartridge.cpp index 35400c5e..d0830193 100755 --- a/bsnes/ui-phoenix/cartridge/cartridge.cpp +++ b/bsnes/ui-phoenix/cartridge/cartridge.cpp @@ -8,19 +8,15 @@ bool Cartridge::loadNormal(const char *filename) { SNES::cartridge.load(SNES::Cartridge::Mode::Normal, lstring() << baseXML); loadMemory(SNES::memory::cartram, baseName, ".srm"); loadMemory(SNES::memory::cartrtc, baseName, ".rtc"); - cheatEditor.load(baseName); - utility.setTitle(notdir(baseName)); - utility.showMessage(string("Loaded ", notdir(baseName))); - config.path.current = dir(baseName); + utility.cartridgeLoaded(); return true; } void Cartridge::unload() { if(SNES::cartridge.loaded() == false) return; - cheatEditor.save(baseName); saveMemory(SNES::memory::cartram, baseName, ".srm"); saveMemory(SNES::memory::cartrtc, baseName, ".rtc"); - SNES::cartridge.unload(); + utility.cartridgeUnloaded(); } bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char *filename) { diff --git a/bsnes/ui-phoenix/config.cpp b/bsnes/ui-phoenix/config.cpp index 4644b87c..17ffd8e5 100755 --- a/bsnes/ui-phoenix/config.cpp +++ b/bsnes/ui-phoenix/config.cpp @@ -14,6 +14,9 @@ void Configuration::create() { attach(video.driver = "", "video.driver"); attach(video.synchronize = false, "video.synchronize"); + attach(video.smooth = true, "video.smooth"); + attach(video.scale = 2, "video.scale"); + attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection"); attach(video.contrast = 100, "video.contrast"); attach(video.brightness = 100, "video.brightness"); attach(video.gamma = 100, "video.gamma"); @@ -22,6 +25,10 @@ void Configuration::create() { attach(audio.driver = "", "audio.driver"); attach(audio.synchronize = true, "audio.synchronize"); attach(audio.mute = false, "audio.mute"); + attach(audio.volume = 100, "audio.volume"); + attach(audio.latency = 60, "audio.latency"); + attach(audio.inputFrequency = 32000, "audio.inputFrequency"); + attach(audio.outputFrequency = 44100, "audio.outputFrequency"); attach(input.driver = "", "input.driver"); diff --git a/bsnes/ui-phoenix/config.hpp b/bsnes/ui-phoenix/config.hpp index 9fed046d..92dba0f0 100755 --- a/bsnes/ui-phoenix/config.hpp +++ b/bsnes/ui-phoenix/config.hpp @@ -8,6 +8,9 @@ struct Configuration : public configuration { struct Video { string driver; bool synchronize; + bool smooth; + unsigned scale; + bool aspectRatioCorrection; unsigned contrast; unsigned brightness; unsigned gamma; @@ -18,6 +21,10 @@ struct Configuration : public configuration { string driver; bool synchronize; bool mute; + unsigned volume; + unsigned latency; + unsigned inputFrequency; + unsigned outputFrequency; } audio; struct Input { diff --git a/bsnes/ui-phoenix/general/file-browser.cpp b/bsnes/ui-phoenix/general/file-browser.cpp index 4f4e37b1..dc7d71f5 100755 --- a/bsnes/ui-phoenix/general/file-browser.cpp +++ b/bsnes/ui-phoenix/general/file-browser.cpp @@ -16,6 +16,7 @@ void FileBrowser::create() { setGeometry(160, 160, 640, y); + pathBox.onActivate = []() { fileBrowser.setFolder(fileBrowser.pathBox.text()); }; browseButton.onTick = { &FileBrowser::folderBrowse, this }; upButton.onTick = { &FileBrowser::folderUp, this }; contentsBox.onActivate = { &FileBrowser::fileActivate, this }; @@ -29,6 +30,10 @@ void FileBrowser::fileOpen(const char *pathname) { } void FileBrowser::setFolder(const char *pathname) { + string path = pathname; + path.rtrim("/"); + if(folder == path) return; + contentsBox.reset(); contents.reset(); @@ -42,6 +47,7 @@ void FileBrowser::setFolder(const char *pathname) { } foreach(item, contents) contentsBox.addItem(item); contentsBox.setSelection(0); + contentsBox.setFocused(); } void FileBrowser::folderBrowse() { @@ -61,7 +67,6 @@ void FileBrowser::fileActivate() { } else { filename = string(folder, "/", filename); cartridge.loadNormal(filename); - SNES::system.power(); setVisible(false); } } diff --git a/bsnes/ui-phoenix/general/main-window.cpp b/bsnes/ui-phoenix/general/main-window.cpp index 639ea249..f2e99856 100755 --- a/bsnes/ui-phoenix/general/main-window.cpp +++ b/bsnes/ui-phoenix/general/main-window.cpp @@ -9,18 +9,42 @@ void MainWindow::create() { system.create(*this, "System"); systemLoadCartridge.create(system, "Load Cartridge ..."); - systemSeparator.create(system); - systemQuit.create(system, "Quit"); + systemSeparator1.create(system); + systemPower.create(system, "Power Cycle"); + systemReset.create(system, "Reset"); + systemSeparator2.create(system); + systemPort1.create(system, "Controller Port 1"); + systemPort1.setEnabled(false); + systemPort2.create(system, "Controller Port 2"); + systemPort2.setEnabled(false); settings.create(*this, "Settings"); + settingsVideoMode.create(settings, "Video Mode"); + settingsVideoMode1x.create(settingsVideoMode, "Scale 1x"); + settingsVideoMode2x.create(settingsVideoMode1x, "Scale 2x"); + settingsVideoMode3x.create(settingsVideoMode1x, "Scale 3x"); + settingsVideoMode4x.create(settingsVideoMode1x, "Scale 4x"); + settingsVideoMode5x.create(settingsVideoMode1x, "Scale 5x"); + if(config.video.scale == 1) settingsVideoMode1x.setChecked(); + if(config.video.scale == 2) settingsVideoMode2x.setChecked(); + if(config.video.scale == 3) settingsVideoMode3x.setChecked(); + if(config.video.scale == 4) settingsVideoMode4x.setChecked(); + if(config.video.scale == 5) settingsVideoMode5x.setChecked(); + settingsVideoModeSeparator.create(settingsVideoMode); + settingsVideoModeAspectRatioCorrection.create(settingsVideoMode, "Correct Aspect Ratio"); + settingsVideoModeAspectRatioCorrection.setChecked(config.video.aspectRatioCorrection); + settingsSmoothVideo.create(settings, "Smooth Video"); + settingsSmoothVideo.setChecked(config.video.smooth); + settingsSeparator1.create(settings); settingsSynchronizeVideo.create(settings, "Synchronize Video"); settingsSynchronizeVideo.setChecked(config.video.synchronize); settingsSynchronizeAudio.create(settings, "Synchronize Audio"); settingsSynchronizeAudio.setChecked(config.audio.synchronize); settingsMuteAudio.create(settings, "Mute Audio"); settingsMuteAudio.setChecked(config.audio.mute); - settingsSeparator.create(settings); + settingsSeparator2.create(settings); settingsVideo.create(settings, "Video Settings ..."); + settingsAudio.create(settings, "Audio Settings ..."); settingsInput.create(settings, "Input Settings ..."); settingsAdvanced.create(settings, "Advanced Settings ..."); @@ -52,7 +76,30 @@ void MainWindow::create() { utility.loadCartridgeNormal(); }; - systemQuit.onTick = []() { application.quit = true; }; + systemPower.onTick = []() { + SNES::system.power(); + utility.showMessage("System was power cycled"); + }; + + systemReset.onTick = []() { + SNES::system.reset(); + utility.showMessage("System was reset"); + }; + + settingsVideoMode1x.onTick = []() { utility.setScale(1); }; + settingsVideoMode2x.onTick = []() { utility.setScale(2); }; + settingsVideoMode3x.onTick = []() { utility.setScale(3); }; + settingsVideoMode4x.onTick = []() { utility.setScale(4); }; + settingsVideoMode5x.onTick = []() { utility.setScale(5); }; + + settingsVideoModeAspectRatioCorrection.onTick = []() { + utility.setAspectRatioCorrection(mainWindow.settingsVideoModeAspectRatioCorrection.checked()); + }; + + settingsSmoothVideo.onTick = []() { + config.video.smooth = mainWindow.settingsSmoothVideo.checked(); + video.set(Video::Filter, (unsigned)config.video.smooth); + }; settingsSynchronizeVideo.onTick = []() { config.video.synchronize = mainWindow.settingsSynchronizeVideo.checked(); @@ -67,6 +114,7 @@ void MainWindow::create() { settingsMuteAudio.onTick = []() { config.audio.mute = mainWindow.settingsMuteAudio.checked(); }; settingsVideo.onTick = []() { videoSettings.setVisible(); }; + settingsAudio.onTick = []() { audioSettings.setVisible(); }; settingsInput.onTick = []() { inputSettings.setVisible(); }; settingsAdvanced.onTick = []() { advancedSettings.setVisible(); }; @@ -98,4 +146,20 @@ void MainWindow::create() { application.quit = true; return false; }; + + synchronize(); +} + +void MainWindow::synchronize() { + if(SNES::cartridge.loaded() == false) { + systemPower.setEnabled(false); + systemReset.setEnabled(false); + toolsStateSave.setEnabled(false); + toolsStateLoad.setEnabled(false); + } else { + systemPower.setEnabled(true); + systemReset.setEnabled(true); + toolsStateSave.setEnabled(true); + toolsStateLoad.setEnabled(true); + } } diff --git a/bsnes/ui-phoenix/general/main-window.hpp b/bsnes/ui-phoenix/general/main-window.hpp index 50b0cbd1..3a4fd35f 100755 --- a/bsnes/ui-phoenix/general/main-window.hpp +++ b/bsnes/ui-phoenix/general/main-window.hpp @@ -1,14 +1,29 @@ struct MainWindow : Window { Menu system; MenuItem systemLoadCartridge; - MenuSeparator systemSeparator; - MenuItem systemQuit; + MenuSeparator systemSeparator1; + MenuItem systemPower; + MenuItem systemReset; + MenuSeparator systemSeparator2; + Menu systemPort1; + Menu systemPort2; Menu settings; + Menu settingsVideoMode; + MenuRadioItem settingsVideoMode1x; + MenuRadioItem settingsVideoMode2x; + MenuRadioItem settingsVideoMode3x; + MenuRadioItem settingsVideoMode4x; + MenuRadioItem settingsVideoMode5x; + MenuSeparator settingsVideoModeSeparator; + MenuCheckItem settingsVideoModeAspectRatioCorrection; + MenuCheckItem settingsSmoothVideo; + MenuSeparator settingsSeparator1; MenuCheckItem settingsSynchronizeVideo; MenuCheckItem settingsSynchronizeAudio; MenuCheckItem settingsMuteAudio; - MenuSeparator settingsSeparator; + MenuSeparator settingsSeparator2; MenuItem settingsVideo; + MenuItem settingsAudio; MenuItem settingsInput; MenuItem settingsAdvanced; Menu tools; @@ -31,6 +46,7 @@ struct MainWindow : Window { Viewport viewport; void create(); + void synchronize(); }; extern MainWindow mainWindow; diff --git a/bsnes/ui-phoenix/input/input.cpp b/bsnes/ui-phoenix/input/input.cpp index eca7ee09..0ddff3f2 100755 --- a/bsnes/ui-phoenix/input/input.cpp +++ b/bsnes/ui-phoenix/input/input.cpp @@ -6,6 +6,8 @@ void InputMapper::AbstractInput::bind() { else if(strend(mapping, ".Down")) type = Type::HatDown; else if(strend(mapping, ".Left")) type = Type::HatLeft; else if(strend(mapping, ".Right")) type = Type::HatRight; + else if(strend(mapping, ".Lo")) type = Type::AxisLo; + else if(strend(mapping, ".Hi")) type = Type::AxisHi; else type = Type::Button; string mappingValue = mapping; @@ -21,6 +23,8 @@ int16_t InputMapper::DigitalInput::poll() { case AbstractInput::Type::HatDown: return (bool)(value & Joypad::HatDown); case AbstractInput::Type::HatLeft: return (bool)(value & Joypad::HatLeft); case AbstractInput::Type::HatRight: return (bool)(value & Joypad::HatRight); + case AbstractInput::Type::AxisLo: return (bool)(value < -16384); + case AbstractInput::Type::AxisHi: return (bool)(value > +16384); } } @@ -206,3 +210,7 @@ int16_t InputMapper::poll(bool port, SNES::Input::Device device, unsigned index, } return 0; } + +int16_t InputMapper::value(unsigned scancode) { + return state[activeState][scancode]; +} diff --git a/bsnes/ui-phoenix/input/input.hpp b/bsnes/ui-phoenix/input/input.hpp index 351d6d60..8cbca811 100755 --- a/bsnes/ui-phoenix/input/input.hpp +++ b/bsnes/ui-phoenix/input/input.hpp @@ -1,6 +1,6 @@ struct InputMapper { struct AbstractInput { - enum class Type : unsigned { Button, HatUp, HatDown, HatLeft, HatRight } type; + enum class Type : unsigned { Button, HatUp, HatDown, HatLeft, HatRight, AxisLo, AxisHi } type; string name; string mapping; unsigned scancode; @@ -76,6 +76,7 @@ struct InputMapper { void bind(); void poll(); int16_t poll(bool port, SNES::Input::Device device, unsigned index, unsigned id); + int16_t value(unsigned scancode); }; extern InputMapper inputMapper; diff --git a/bsnes/ui-phoenix/main.cpp b/bsnes/ui-phoenix/main.cpp index b24013ff..e3f1065f 100755 --- a/bsnes/ui-phoenix/main.cpp +++ b/bsnes/ui-phoenix/main.cpp @@ -11,10 +11,10 @@ void Application::main(int argc, char **argv) { inputMapper.create(); char temp[PATH_MAX]; - config.path.base = realpath(argv[0], temp); + if(realpath(argv[0], temp)) config.path.base = temp; config.path.base.transform("\\", "/"); config.path.base = dir(config.path.base); - config.path.user = userpath(temp); + if(userpath(temp)) config.path.user = temp; config.path.user.transform("\\", "/"); if(strend(config.path.user, "/") == false) config.path.user.append("/"); config.path.user.append(".bsnes/"); @@ -41,16 +41,18 @@ void Application::main(int argc, char **argv) { mainWindow.create(); fileBrowser.create(); videoSettings.create(); + audioSettings.create(); inputSettings.create(); advancedSettings.create(); cheatEditor.create(); + utility.setScale(config.video.scale); mainWindow.setVisible(); os.run(); video.driver(config.video.driver); video.set(Video::Handle, mainWindow.viewport.handle()); video.set(Video::Synchronize, config.video.synchronize); - video.set(Video::Filter, (unsigned)Video::FilterLinear); + video.set(Video::Filter, (unsigned)config.video.smooth); if(video.init() == false) { MessageWindow::critical(mainWindow, "Failed to initialize video."); video.driver("None"); @@ -60,7 +62,11 @@ void Application::main(int argc, char **argv) { audio.driver(config.audio.driver); audio.set(Audio::Handle, mainWindow.viewport.handle()); audio.set(Audio::Synchronize, config.audio.synchronize); - audio.set(Audio::Frequency, (unsigned)32000); + audio.set(Audio::Volume, config.audio.volume); + audio.set(Audio::Latency, config.audio.latency); + audio.set(Audio::Frequency, config.audio.outputFrequency); + audio.set(Audio::Resample, true); + audio.set(Audio::ResampleRatio, (double)config.audio.inputFrequency / (double)config.audio.outputFrequency); if(audio.init() == false) { MessageWindow::critical(mainWindow, "Failed to initialize audio."); audio.driver("None"); @@ -76,10 +82,7 @@ void Application::main(int argc, char **argv) { } SNES::system.init(&interface); - if(argc == 2) { - cartridge.loadNormal(argv[1]); - SNES::system.power(); - } + if(argc == 2) cartridge.loadNormal(argv[1]); while(quit == false) { os.run(); diff --git a/bsnes/ui-phoenix/settings/audio.cpp b/bsnes/ui-phoenix/settings/audio.cpp new file mode 100755 index 00000000..87864467 --- /dev/null +++ b/bsnes/ui-phoenix/settings/audio.cpp @@ -0,0 +1,33 @@ +AudioSettings audioSettings; + +void AudioSettings::create() { + application.windows.append(this); + Window::create(0, 0, 256, 256, "Audio Settings"); + setDefaultFont(application.proportionalFont); + + unsigned x = 5, y = 5; + + volumeLabel.create(*this, x, y, 70, Style::SliderHeight, "Volume:"); + volumeValue.create(*this, x + 70, y, 60, Style::SliderHeight, "100%"); + volumeSlider.create(*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5; + volumeSlider.setPosition(config.audio.volume); + + frequencyLabel.create(*this, x, y, 70, Style::SliderHeight, "Frequency:"); + frequencyValue.create(*this, x + 70, y, 60, Style::SliderHeight, "32000hz"); + frequencySlider.create(*this, x + 130, y, 300, Style::SliderHeight, 2001); y += Style::SliderHeight + 5; + frequencySlider.setPosition(config.audio.inputFrequency - 31000); + + volumeSlider.onChange = []() { + config.audio.volume = audioSettings.volumeSlider.position(); + audio.set(Audio::Volume, config.audio.volume); + audioSettings.volumeValue.setText(string(config.audio.volume, "%")); + }; + + frequencySlider.onChange = []() { + config.audio.inputFrequency = audioSettings.frequencySlider.position() + 31000; + audio.set(Audio::ResampleRatio, (double)config.audio.inputFrequency / (double)config.audio.outputFrequency); + audioSettings.frequencyValue.setText(string(config.audio.inputFrequency, "hz")); + }; + + setGeometry(160, 160, 440, y); +} diff --git a/bsnes/ui-phoenix/settings/audio.hpp b/bsnes/ui-phoenix/settings/audio.hpp new file mode 100755 index 00000000..6bf0e63a --- /dev/null +++ b/bsnes/ui-phoenix/settings/audio.hpp @@ -0,0 +1,12 @@ +struct AudioSettings : Window { + Label volumeLabel; + Label volumeValue; + HorizontalSlider volumeSlider; + Label frequencyLabel; + Label frequencyValue; + HorizontalSlider frequencySlider; + + void create(); +}; + +extern AudioSettings audioSettings; diff --git a/bsnes/ui-phoenix/settings/input.cpp b/bsnes/ui-phoenix/settings/input.cpp index a64e5838..6d781cae 100755 --- a/bsnes/ui-phoenix/settings/input.cpp +++ b/bsnes/ui-phoenix/settings/input.cpp @@ -17,7 +17,7 @@ void InputSettings::create() { deviceLabel.create(*this, x + 255, y, 50, Style::ComboBoxHeight, "Device:"); deviceBox.create(*this, x + 305, y, 200, Style::ComboBoxHeight); y += Style::ComboBoxHeight + 5; - mappingList.create(*this, x, y, 505, 300, "Name\tMapping"); y += 300 + 5; + mappingList.create(*this, x, y, 505, 265, "Name\tMapping"); y += 265 + 5; mappingList.setHeaderVisible(); mappingList.setFocused(); @@ -104,8 +104,41 @@ void InputSettings::inputEvent(uint16_t scancode, int16_t value) { else if(value == Joypad::HatDown) setMapping(string(mapping, ".Down")); else if(value == Joypad::HatLeft) setMapping(string(mapping, ".Left")); else if(value == Joypad::HatRight) setMapping(string(mapping, ".Right")); + } else if(Joypad::isAnyAxis(scancode)) { + if(joypadsCalibrated == false) return calibrateJoypads(); + unsigned joypadNumber = Joypad::numberDecode(scancode); + unsigned axisNumber = Joypad::axisDecode(scancode); + int16_t calibration = joypadCalibration[joypadNumber][axisNumber]; + if(calibration > -12288 && calibration < +12288 && value < -24576) setMapping(string(mapping, ".Lo")); + else if(calibration > -12288 && calibration < +12288 && value > +24576) setMapping(string(mapping, ".Hi")); + else if(calibration <= -12288 && value >= +12288) setMapping(string(mapping, ".Hi")); + else if(calibration >= +12288 && value <= -12288) setMapping(string(mapping, ".Lo")); } else if(Joypad::isAnyButton(scancode) && value) { setMapping(mapping); } } } + +void InputSettings::calibrateJoypads() { + if(joypadsCalibrating == true) return; + joypadsCalibrating = true; + MessageWindow::information(*this, + "Analog joypads must be calibrated prior to use.\n\n" + "Please move all analog axes, and press all analog buttons.\n" + "Please do this for every controller you wish to use.\n" + "Once finished, please let go of all axes and buttons, and press OK." + ); + inputMapper.poll(); + for(unsigned j = 0; j < Joypad::Count &&j<2; j++) { + for(unsigned a = 0; a < Joypad::Axes; a++) { + joypadCalibration[j][a] = inputMapper.value(joypad(j).axis(a)); + } + } + joypadsCalibrating = false; + joypadsCalibrated = true; +} + +InputSettings::InputSettings() { + joypadsCalibrated = false; + joypadsCalibrating = false; +} diff --git a/bsnes/ui-phoenix/settings/input.hpp b/bsnes/ui-phoenix/settings/input.hpp index 10d3e0dc..4758e291 100755 --- a/bsnes/ui-phoenix/settings/input.hpp +++ b/bsnes/ui-phoenix/settings/input.hpp @@ -6,9 +6,15 @@ struct InputSettings : Window { ListBox mappingList; void inputEvent(uint16_t scancode, int16_t value); + void calibrateJoypads(); void create(); + InputSettings(); private: + bool joypadsCalibrated; + bool joypadsCalibrating; + int16_t joypadCalibration[Joypad::Count][Joypad::Axes]; + void portChanged(); void deviceChanged(); void setMapping(const char *mapping); diff --git a/bsnes/ui-phoenix/settings/settings.cpp b/bsnes/ui-phoenix/settings/settings.cpp index 7cd1be29..dea0cf30 100755 --- a/bsnes/ui-phoenix/settings/settings.cpp +++ b/bsnes/ui-phoenix/settings/settings.cpp @@ -1,4 +1,5 @@ #include "../base.hpp" #include "video.cpp" +#include "audio.cpp" #include "input.cpp" #include "advanced.cpp" diff --git a/bsnes/ui-phoenix/settings/settings.hpp b/bsnes/ui-phoenix/settings/settings.hpp index dee4e0e8..0279b3ba 100755 --- a/bsnes/ui-phoenix/settings/settings.hpp +++ b/bsnes/ui-phoenix/settings/settings.hpp @@ -1,3 +1,4 @@ #include "video.hpp" +#include "audio.hpp" #include "input.hpp" #include "advanced.hpp" diff --git a/bsnes/ui-phoenix/settings/video.cpp b/bsnes/ui-phoenix/settings/video.cpp index bf36f077..332da6d0 100755 --- a/bsnes/ui-phoenix/settings/video.cpp +++ b/bsnes/ui-phoenix/settings/video.cpp @@ -22,9 +22,9 @@ void VideoSettings::create() { gammaValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%"); gammaSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5; - gammaRampCheck.create (*this, x, y, 430, 15, "Enable NTSC gamma ramp simulation"); y += 15; + gammaRampCheck.create (*this, x, y, 430, Style::CheckBoxHeight, "Enable NTSC gamma ramp simulation"); y += Style::CheckBoxHeight + 5; - setGeometry(160, 160, 440, y + 5); + setGeometry(160, 160, 440, y); contrastSlider.setPosition(config.video.contrast); brightnessSlider.setPosition(config.video.brightness); diff --git a/bsnes/ui-phoenix/utility/utility.cpp b/bsnes/ui-phoenix/utility/utility.cpp index dabc8975..51adc5a2 100755 --- a/bsnes/ui-phoenix/utility/utility.cpp +++ b/bsnes/ui-phoenix/utility/utility.cpp @@ -11,7 +11,14 @@ void Utility::setTitle(const char *text) { void Utility::updateStatus() { time_t currentTime = time(0); - string text = ((currentTime - statusTime) > 3) ? statusText : statusMessage; + string text; + if((currentTime - statusTime) <= 3) { + text = statusMessage; + } else if(SNES::cartridge.loaded() == false) { + text = "No cartridge loaded"; + } else { + text = statusText; + } if(text != statusCurrentText) { mainWindow.setStatusText(statusCurrentText = text); } @@ -27,6 +34,35 @@ void Utility::showMessage(const char *text) { statusTime = time(0); } +void Utility::setScale(unsigned scale) { + config.video.scale = scale; + unsigned width = 256 * scale; + unsigned height = 224 * scale; + if(config.video.aspectRatioCorrection) width *= 54.0 / 47.0; //PAL = 32.0 / 23.0 + mainWindow.viewport.setGeometry(0, 0, width, height); + mainWindow.setGeometry(128, 128, width, height); +} + +void Utility::setAspectRatioCorrection(bool aspectRatioCorrection) { + config.video.aspectRatioCorrection = aspectRatioCorrection; + setScale(config.video.scale); +} + +void Utility::cartridgeLoaded() { + SNES::system.power(); + cheatEditor.load(cartridge.baseName); + mainWindow.synchronize(); + utility.setTitle(notdir(cartridge.baseName)); + utility.showMessage(string("Loaded ", notdir(cartridge.baseName))); + config.path.current = dir(cartridge.baseName); +} + +void Utility::cartridgeUnloaded() { + SNES::cartridge.unload(); + cheatEditor.save(cartridge.baseName); + mainWindow.synchronize(); +} + void Utility::loadCartridgeNormal() { if(config.settings.useNativeDialogs == false) { fileBrowser.fileOpen(config.path.current); diff --git a/bsnes/ui-phoenix/utility/utility.hpp b/bsnes/ui-phoenix/utility/utility.hpp index d6879630..c8b0e7cd 100755 --- a/bsnes/ui-phoenix/utility/utility.hpp +++ b/bsnes/ui-phoenix/utility/utility.hpp @@ -1,9 +1,15 @@ -struct Utility { +struct Utility : property { void setTitle(const char *text); void updateStatus(); void setStatus(const char *text); void showMessage(const char *text); + void setScale(unsigned scale); + void setAspectRatioCorrection(bool aspectRatioCorrection); + + void cartridgeLoaded(); + void cartridgeUnloaded(); + void loadCartridgeNormal(); void saveState(unsigned slot); void loadState(unsigned slot);