diff --git a/bsnes/Makefile b/bsnes/Makefile index 6c66ea06..739bc6d0 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,6 +1,6 @@ include nall/Makefile snes := snes -profile := performance +profile := compatibility ui := ui-qt # compiler diff --git a/bsnes/launcher/launcher.cpp b/bsnes/launcher/launcher.cpp index 0665f20f..fc93e8d1 100755 --- a/bsnes/launcher/launcher.cpp +++ b/bsnes/launcher/launcher.cpp @@ -46,7 +46,7 @@ int main(int argc, char **argv) { PROCESS_INFORMATION pi; memset(&si, 0, sizeof(STARTUPINFOW)); if(!CreateProcessW(nall::utf16_t(fileName), GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { - MessageBox(0, string("Error: unable to locate binary file: ", binaryName), "bsnes", MB_OK); + MessageBoxA(0, string("Error: unable to locate binary file: ", binaryName), "bsnes", MB_OK); } #endif diff --git a/bsnes/nall/directory.hpp b/bsnes/nall/directory.hpp new file mode 100755 index 00000000..85e9acaf --- /dev/null +++ b/bsnes/nall/directory.hpp @@ -0,0 +1,129 @@ +#ifndef NALL_DIRECTORY_HPP +#define NALL_DIRECTORY_HPP + +#include +#include +#include + +#if defined(_WIN32) + #include +#else + #include + #include + #include +#endif + +namespace nall { + +struct directory { + static lstring folders(const char *pathname); + static lstring files(const char *pathname); + static lstring contents(const char *pathname); +}; + +#if defined(_WIN32) + inline lstring directory::folders(const char *pathname) { + lstring list; + string path = pathname; + path.transform("/", "\\"); + if(!strend(path, "\\")) path.append("\\"); + path.append("*"); + HANDLE handle; + WIN32_FIND_DATA data; + handle = FindFirstFile(utf16_t(path), &data); + if(handle != INVALID_HANDLE_VALUE) { + if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { + if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + list.append(string(utf8_t(data.cFileName), "/")); + } + } + while(FindNextFile(handle, &data) != false) { + if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { + if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + list.append(string(utf8_t(data.cFileName), "/")); + } + } + } + FindClose(handle); + } + sort(&list[0], list.size()); + return list; + } + + inline lstring directory::files(const char *pathname) { + lstring list; + string path = pathname; + path.transform("/", "\\"); + if(!strend(path, "\\")) path.append("\\"); + path.append("*"); + HANDLE handle; + WIN32_FIND_DATA data; + handle = FindFirstFile(utf16_t(path), &data); + if(handle != INVALID_HANDLE_VALUE) { + if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + list.append(utf8_t(data.cFileName)); + } + while(FindNextFile(handle, &data) != false) { + if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + list.append(utf8_t(data.cFileName)); + } + } + FindClose(handle); + } + sort(&list[0], list.size()); + return list; + } + + inline lstring directory::contents(const char *pathname) { + lstring folders = directory::folders(pathname); + lstring files = directory::files(pathname); + foreach(file, files) folders.append(file); + return folders; + } +#else + inline lstring directory::folders(const char *pathname) { + lstring list; + DIR *dp; + struct dirent *ep; + dp = opendir(pathname); + if(dp) { + while(ep = readdir(dp)) { + if(!strcmp(ep->d_name, ".")) continue; + if(!strcmp(ep->d_name, "..")) continue; + if(ep->d_type & DT_DIR) list.append(string(ep->d_name, "/")); + } + closedir(dp); + } + sort(&list[0], list.size()); + return list; + + } + + inline lstring directory::files(const char *pathname) { + lstring list; + DIR *dp; + struct dirent *ep; + dp = opendir(pathname); + if(dp) { + while(ep = readdir(dp)) { + if(!strcmp(ep->d_name, ".")) continue; + if(!strcmp(ep->d_name, "..")) continue; + if((ep->d_type & DT_DIR) == 0) list.append(ep->d_name); + } + closedir(dp); + } + sort(&list[0], list.size()); + return list; + } + + inline lstring directory::contents(const char *pathname) { + lstring folders = directory::folders(pathname); + lstring files = directory::files(pathname); + foreach(file, files) folders.append(file); + return folders; + } +#endif + +} + +#endif diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp index 6855bdd3..72eeec09 100755 --- a/bsnes/nall/platform.hpp +++ b/bsnes/nall/platform.hpp @@ -103,15 +103,6 @@ strcpy(path, nall::utf8_t(fp)); return path; } - - inline void initialize_arguments(int &argc, char **&argv) { - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = new char*[argc]; - for(unsigned i = 0; i < argc; i++) { - argv[i] = new char[_MAX_PATH]; - strcpy(argv[i], nall::utf8_t(wargv[i])); - } - } #else //realpath() already exists @@ -125,9 +116,6 @@ inline char *getcwd(char *path) { return getcwd(path, PATH_MAX); } - - inline void initialize_arguments(int &argc, char **&argv) { - } #endif #endif diff --git a/bsnes/nall/utf8.hpp b/bsnes/nall/utf8.hpp index 5def74e0..f5597b85 100755 --- a/bsnes/nall/utf8.hpp +++ b/bsnes/nall/utf8.hpp @@ -6,9 +6,11 @@ #if defined(_WIN32) +#undef UNICODE #undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 #undef NOMINMAX +#define UNICODE +#define _WIN32_WINNT 0x0501 #define NOMINMAX #include #undef interface @@ -68,6 +70,15 @@ namespace nall { private: char *buffer; }; + + inline void utf8_args(int &argc, char **&argv) { + wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); + argv = new char*[argc]; + for(unsigned i = 0; i < argc; i++) { + argv[i] = new char[_MAX_PATH]; + strcpy(argv[i], nall::utf8_t(wargv[i])); + } + } } #endif //if defined(_WIN32) diff --git a/bsnes/phoenix/gtk/combobox.cpp b/bsnes/phoenix/gtk/combobox.cpp index d802a248..8650dd21 100755 --- a/bsnes/phoenix/gtk/combobox.cpp +++ b/bsnes/phoenix/gtk/combobox.cpp @@ -1,5 +1,5 @@ void ComboBox_change(ComboBox *self) { - if(self->onChange) self->onChange(); + if(self->object->locked == false && self->onChange) self->onChange(); } void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { @@ -19,9 +19,11 @@ void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un } void ComboBox::reset() { + object->locked = true; for(signed i = counter - 1; i >= 0; i--) { gtk_combo_box_remove_text(GTK_COMBO_BOX(object->widget), i); } + object->locked = false; counter = 0; } @@ -35,7 +37,9 @@ unsigned ComboBox::selection() { } void ComboBox::setSelection(unsigned item) { + object->locked = true; gtk_combo_box_set_active(GTK_COMBO_BOX(object->widget), item); + object->locked = false; } ComboBox::ComboBox() { diff --git a/bsnes/phoenix/gtk/editbox.cpp b/bsnes/phoenix/gtk/editbox.cpp index d09b59a0..34dc0eef 100755 --- a/bsnes/phoenix/gtk/editbox.cpp +++ b/bsnes/phoenix/gtk/editbox.cpp @@ -19,6 +19,10 @@ void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns gtk_widget_show(object->widget); } +void EditBox::setFocused() { + gtk_widget_grab_focus(object->subWidget); +} + void EditBox::setEditable(bool editable) { gtk_text_view_set_editable(GTK_TEXT_VIEW(object->subWidget), editable); } diff --git a/bsnes/phoenix/gtk/gtk.cpp b/bsnes/phoenix/gtk/gtk.cpp index 109cb6ff..4145f58f 100755 --- a/bsnes/phoenix/gtk/gtk.cpp +++ b/bsnes/phoenix/gtk/gtk.cpp @@ -49,9 +49,8 @@ bool OS::pending() { return gtk_events_pending(); } -bool OS::run() { - gtk_main_iteration_do(false); - return gtk_events_pending(); +void OS::run() { + while(pending()) gtk_main_iteration_do(false); } void OS::main() { diff --git a/bsnes/phoenix/gtk/gtk.hpp b/bsnes/phoenix/gtk/gtk.hpp index 3cfa3ba9..a3facdf1 100755 --- a/bsnes/phoenix/gtk/gtk.hpp +++ b/bsnes/phoenix/gtk/gtk.hpp @@ -75,7 +75,7 @@ struct Widget : Object { bool enabled(); void setEnabled(bool enabled = true); virtual bool focused(); - void setFocused(); + virtual void setFocused(); }; struct Window : Widget { @@ -83,6 +83,7 @@ struct Window : Widget { nall::function onClose; void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); bool focused(); + void setFocused(); void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); void setDefaultFont(Font &font); void setFont(Font &font); @@ -135,6 +136,7 @@ private: struct EditBox : Widget { nall::function onChange; void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); + void setFocused(); void setEditable(bool editable = true); void setWordWrap(bool wordWrap = true); nall::string text(); @@ -157,6 +159,7 @@ struct ListBox : Widget { nall::function onActivate; nall::function onChange; void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); + void setFocused(); void setHeaderVisible(bool headerVisible = true); void setFont(Font &font); void reset(); @@ -226,7 +229,7 @@ struct MessageWindow : Object { struct OS : Object { bool pending(); - bool run(); + void run(); void main(); void quit(); unsigned desktopWidth(); diff --git a/bsnes/phoenix/gtk/listbox.cpp b/bsnes/phoenix/gtk/listbox.cpp index c142e4ba..8668e8f8 100755 --- a/bsnes/phoenix/gtk/listbox.cpp +++ b/bsnes/phoenix/gtk/listbox.cpp @@ -56,6 +56,10 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns gtk_widget_show(object->widget); } +void ListBox::setFocused() { + gtk_widget_grab_focus(object->subWidget); +} + void ListBox::setHeaderVisible(bool visible) { gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible); } @@ -76,6 +80,9 @@ void ListBox::reset() { listBox->selection = -1; gtk_list_store_clear(GTK_LIST_STORE(listBox->store)); gtk_tree_view_set_model(GTK_TREE_VIEW(object->subWidget), GTK_TREE_MODEL(listBox->store)); + //reset gtk_scrolled_window scrollbar position to 0,0 (top-left), as ListBox is now empty + gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(object->widget), 0); + gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(object->widget), 0); } void ListBox::resizeColumnsToContent() { diff --git a/bsnes/phoenix/gtk/window.cpp b/bsnes/phoenix/gtk/window.cpp index 83c140e3..e8fc64da 100755 --- a/bsnes/phoenix/gtk/window.cpp +++ b/bsnes/phoenix/gtk/window.cpp @@ -43,6 +43,10 @@ bool Window::focused() { return gtk_window_is_active(GTK_WINDOW(object->widget)); } +void Window::setFocused() { + gtk_window_present(GTK_WINDOW(object->widget)); +} + void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { gtk_window_move(GTK_WINDOW(object->widget), x, y); gtk_widget_set_size_request(object->formContainer, width, height); diff --git a/bsnes/phoenix/qt/label.cpp b/bsnes/phoenix/qt/label.cpp index 6a18e96a..87c97a1a 100755 --- a/bsnes/phoenix/qt/label.cpp +++ b/bsnes/phoenix/qt/label.cpp @@ -6,6 +6,10 @@ void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsig label->show(); } +void Label::setText(const char *text) { + label->setText(text); +} + Label::Label() { label = new Label::Data(*this); widget->widget = label; diff --git a/bsnes/phoenix/qt/qt.cpp b/bsnes/phoenix/qt/qt.cpp index 908b9203..02cbd03e 100755 --- a/bsnes/phoenix/qt/qt.cpp +++ b/bsnes/phoenix/qt/qt.cpp @@ -39,9 +39,8 @@ bool OS::pending() { return QApplication::hasPendingEvents(); } -bool OS::run() { +void OS::run() { QApplication::processEvents(); - return QApplication::hasPendingEvents(); } void OS::main() { diff --git a/bsnes/phoenix/qt/qt.hpp b/bsnes/phoenix/qt/qt.hpp index 1bf28b86..e3e240e9 100755 --- a/bsnes/phoenix/qt/qt.hpp +++ b/bsnes/phoenix/qt/qt.hpp @@ -125,6 +125,7 @@ struct Window : Widget { nall::function onClose; void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); + void setDefaultFont(Font &font); void setFont(Font &font); void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); void setTitle(const char *text); @@ -208,6 +209,7 @@ struct HorizontalSlider : Widget { struct Label : Widget { void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); + void setText(const char *text); Label(); //private: struct Data; @@ -304,7 +306,7 @@ struct MessageWindow : Object { struct OS : Object { bool pending(); - bool run(); + void run(); void main(); void quit(); unsigned desktopWidth(); diff --git a/bsnes/phoenix/qt/qt.moc b/bsnes/phoenix/qt/qt.moc new file mode 100755 index 00000000..ce1b6754 --- /dev/null +++ b/bsnes/phoenix/qt/qt.moc @@ -0,0 +1,925 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'qt.moc.hpp' +** +** Created: Sat Sep 25 06:31:14 2010 +** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'qt.moc.hpp' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.6.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_MenuItem__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 16, 15, 15, 15, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_MenuItem__Data[] = { + "MenuItem::Data\0\0onTick()\0" +}; + +const QMetaObject MenuItem::Data::staticMetaObject = { + { &QAction::staticMetaObject, qt_meta_stringdata_MenuItem__Data, + qt_meta_data_MenuItem__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MenuItem::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MenuItem::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MenuItem::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MenuItem__Data)) + return static_cast(const_cast< Data*>(this)); + return QAction::qt_metacast(_clname); +} + +int MenuItem::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QAction::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_MenuCheckItem__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 21, 20, 20, 20, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_MenuCheckItem__Data[] = { + "MenuCheckItem::Data\0\0onTick()\0" +}; + +const QMetaObject MenuCheckItem::Data::staticMetaObject = { + { &QAction::staticMetaObject, qt_meta_stringdata_MenuCheckItem__Data, + qt_meta_data_MenuCheckItem__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MenuCheckItem::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MenuCheckItem::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MenuCheckItem::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MenuCheckItem__Data)) + return static_cast(const_cast< Data*>(this)); + return QAction::qt_metacast(_clname); +} + +int MenuCheckItem::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QAction::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_MenuRadioItem__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 21, 20, 20, 20, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_MenuRadioItem__Data[] = { + "MenuRadioItem::Data\0\0onTick()\0" +}; + +const QMetaObject MenuRadioItem::Data::staticMetaObject = { + { &QAction::staticMetaObject, qt_meta_stringdata_MenuRadioItem__Data, + qt_meta_data_MenuRadioItem__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MenuRadioItem::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MenuRadioItem::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MenuRadioItem::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MenuRadioItem__Data)) + return static_cast(const_cast< Data*>(this)); + return QAction::qt_metacast(_clname); +} + +int MenuRadioItem::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QAction::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_Window__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_Window__Data[] = { + "Window::Data\0" +}; + +const QMetaObject Window::Data::staticMetaObject = { + { &QWidget::staticMetaObject, qt_meta_stringdata_Window__Data, + qt_meta_data_Window__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &Window::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *Window::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *Window::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Window__Data)) + return static_cast(const_cast< Data*>(this)); + return QWidget::qt_metacast(_clname); +} + +int Window::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +static const uint qt_meta_data_Button__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 14, 13, 13, 13, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_Button__Data[] = { + "Button::Data\0\0onTick()\0" +}; + +const QMetaObject Button::Data::staticMetaObject = { + { &QPushButton::staticMetaObject, qt_meta_stringdata_Button__Data, + qt_meta_data_Button__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &Button::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *Button::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *Button::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Button__Data)) + return static_cast(const_cast< Data*>(this)); + return QPushButton::qt_metacast(_clname); +} + +int Button::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QPushButton::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_Canvas__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_Canvas__Data[] = { + "Canvas::Data\0" +}; + +const QMetaObject Canvas::Data::staticMetaObject = { + { &QWidget::staticMetaObject, qt_meta_stringdata_Canvas__Data, + qt_meta_data_Canvas__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &Canvas::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *Canvas::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *Canvas::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Canvas__Data)) + return static_cast(const_cast< Data*>(this)); + return QWidget::qt_metacast(_clname); +} + +int Canvas::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +static const uint qt_meta_data_CheckBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 16, 15, 15, 15, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_CheckBox__Data[] = { + "CheckBox::Data\0\0onTick()\0" +}; + +const QMetaObject CheckBox::Data::staticMetaObject = { + { &QCheckBox::staticMetaObject, qt_meta_stringdata_CheckBox__Data, + qt_meta_data_CheckBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &CheckBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *CheckBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *CheckBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_CheckBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QCheckBox::qt_metacast(_clname); +} + +int CheckBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QCheckBox::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_ComboBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 16, 15, 15, 15, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_ComboBox__Data[] = { + "ComboBox::Data\0\0onChange()\0" +}; + +const QMetaObject ComboBox::Data::staticMetaObject = { + { &QComboBox::staticMetaObject, qt_meta_stringdata_ComboBox__Data, + qt_meta_data_ComboBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &ComboBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *ComboBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *ComboBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_ComboBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QComboBox::qt_metacast(_clname); +} + +int ComboBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QComboBox::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_EditBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 15, 14, 14, 14, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_EditBox__Data[] = { + "EditBox::Data\0\0onChange()\0" +}; + +const QMetaObject EditBox::Data::staticMetaObject = { + { &QTextEdit::staticMetaObject, qt_meta_stringdata_EditBox__Data, + qt_meta_data_EditBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &EditBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *EditBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *EditBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_EditBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QTextEdit::qt_metacast(_clname); +} + +int EditBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QTextEdit::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_HorizontalSlider__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 24, 23, 23, 23, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_HorizontalSlider__Data[] = { + "HorizontalSlider::Data\0\0onChange()\0" +}; + +const QMetaObject HorizontalSlider::Data::staticMetaObject = { + { &QSlider::staticMetaObject, qt_meta_stringdata_HorizontalSlider__Data, + qt_meta_data_HorizontalSlider__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &HorizontalSlider::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *HorizontalSlider::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *HorizontalSlider::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_HorizontalSlider__Data)) + return static_cast(const_cast< Data*>(this)); + return QSlider::qt_metacast(_clname); +} + +int HorizontalSlider::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QSlider::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_Label__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_Label__Data[] = { + "Label::Data\0" +}; + +const QMetaObject Label::Data::staticMetaObject = { + { &QLabel::staticMetaObject, qt_meta_stringdata_Label__Data, + qt_meta_data_Label__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &Label::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *Label::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *Label::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Label__Data)) + return static_cast(const_cast< Data*>(this)); + return QLabel::qt_metacast(_clname); +} + +int Label::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QLabel::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +static const uint qt_meta_data_ListBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 2, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 15, 14, 14, 14, 0x0a, + 28, 14, 14, 14, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_ListBox__Data[] = { + "ListBox::Data\0\0onActivate()\0onChange()\0" +}; + +const QMetaObject ListBox::Data::staticMetaObject = { + { &QTreeWidget::staticMetaObject, qt_meta_stringdata_ListBox__Data, + qt_meta_data_ListBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &ListBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *ListBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *ListBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_ListBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QTreeWidget::qt_metacast(_clname); +} + +int ListBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QTreeWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onActivate(); break; + case 1: onChange(); break; + default: ; + } + _id -= 2; + } + return _id; +} +static const uint qt_meta_data_RadioBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 16, 15, 15, 15, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_RadioBox__Data[] = { + "RadioBox::Data\0\0onTick()\0" +}; + +const QMetaObject RadioBox::Data::staticMetaObject = { + { &QRadioButton::staticMetaObject, qt_meta_stringdata_RadioBox__Data, + qt_meta_data_RadioBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &RadioBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *RadioBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *RadioBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_RadioBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QRadioButton::qt_metacast(_clname); +} + +int RadioBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QRadioButton::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTick(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_TextBox__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 15, 14, 14, 14, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_TextBox__Data[] = { + "TextBox::Data\0\0onChange()\0" +}; + +const QMetaObject TextBox::Data::staticMetaObject = { + { &QLineEdit::staticMetaObject, qt_meta_stringdata_TextBox__Data, + qt_meta_data_TextBox__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &TextBox::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *TextBox::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *TextBox::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_TextBox__Data)) + return static_cast(const_cast< Data*>(this)); + return QLineEdit::qt_metacast(_clname); +} + +int TextBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QLineEdit::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_VerticalSlider__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 22, 21, 21, 21, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_VerticalSlider__Data[] = { + "VerticalSlider::Data\0\0onChange()\0" +}; + +const QMetaObject VerticalSlider::Data::staticMetaObject = { + { &QSlider::staticMetaObject, qt_meta_stringdata_VerticalSlider__Data, + qt_meta_data_VerticalSlider__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &VerticalSlider::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *VerticalSlider::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *VerticalSlider::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_VerticalSlider__Data)) + return static_cast(const_cast< Data*>(this)); + return QSlider::qt_metacast(_clname); +} + +int VerticalSlider::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QSlider::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} +static const uint qt_meta_data_OS__Data[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_OS__Data[] = { + "OS::Data\0" +}; + +const QMetaObject OS::Data::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_OS__Data, + qt_meta_data_OS__Data, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &OS::Data::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *OS::Data::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *OS::Data::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_OS__Data)) + return static_cast(const_cast< Data*>(this)); + return QObject::qt_metacast(_clname); +} + +int OS::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/bsnes/phoenix/qt/window.cpp b/bsnes/phoenix/qt/window.cpp index 6902a58e..893cb183 100755 --- a/bsnes/phoenix/qt/window.cpp +++ b/bsnes/phoenix/qt/window.cpp @@ -2,22 +2,24 @@ void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, con window->setWindowTitle(text); window->move(x, y); - window->layout = new QVBoxLayout; + window->layout = new QVBoxLayout(window); window->layout->setMargin(0); window->layout->setSpacing(0); window->layout->setSizeConstraint(QLayout::SetFixedSize); window->setLayout(window->layout); - window->menuBar = new QMenuBar; - window->menuBar->hide(); + window->menuBar = new QMenuBar(window); + window->menuBar->setVisible(false); window->layout->addWidget(window->menuBar); - window->container = new QWidget; + window->container = new QWidget(window); window->container->setFixedSize(width, height); + window->container->setVisible(true); window->layout->addWidget(window->container); - window->statusBar = new QStatusBar; + window->statusBar = new QStatusBar(window); window->statusBar->setSizeGripEnabled(false); + window->statusBar->setVisible(false); window->layout->addWidget(window->statusBar); } @@ -26,9 +28,12 @@ void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height window->move(x, y); } -void Window::setFont(Font &font) { +void Window::setDefaultFont(Font &font) { window->defaultFont = font.font; window->menuBar->setFont(*font.font); +} + +void Window::setFont(Font &font) { window->statusBar->setFont(*font.font); } diff --git a/bsnes/phoenix/windows/windows.cpp b/bsnes/phoenix/windows/windows.cpp index b00ecd42..4623ca07 100755 --- a/bsnes/phoenix/windows/windows.cpp +++ b/bsnes/phoenix/windows/windows.cpp @@ -32,6 +32,8 @@ namespace phoenix { OS &os = OS::handle(); Window Window::None; +static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM); + OS& OS::handle() { static OS os; return os; @@ -42,20 +44,27 @@ bool OS::pending() { return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); } -bool OS::run() { - MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { - if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); +void OS::run() { + while(pending()) { + MSG msg; + if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) { + OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + } + if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } } - return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); } void OS::main() { MSG msg; while(GetMessage(&msg, 0, 0, 0)) { + if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) { + OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + } if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -194,6 +203,24 @@ string OS::fileSave(Window &parent, const char *filter, const char *path) { return utf8_t(wfilename); } +static void OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + switch(msg) { + case WM_KEYDOWN: { + GUITHREADINFO info; + memset(&info, 0, sizeof(GUITHREADINFO)); + 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(); + } + } + } + } +} + static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { Object *object_ptr = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!object_ptr || !dynamic_cast(object_ptr)) return DefWindowProc(hwnd, msg, wparam, lparam); diff --git a/bsnes/phoenix/windows/windows.hpp b/bsnes/phoenix/windows/windows.hpp index 993eefeb..1cb4bc56 100755 --- a/bsnes/phoenix/windows/windows.hpp +++ b/bsnes/phoenix/windows/windows.hpp @@ -254,7 +254,7 @@ struct MessageWindow : Object { struct OS : Object { bool pending(); - bool run(); + void run(); void main(); void quit(); unsigned desktopWidth(); diff --git a/bsnes/ruby/input/rawinput.cpp b/bsnes/ruby/input/rawinput.cpp index d54826da..ff46f285 100755 --- a/bsnes/ruby/input/rawinput.cpp +++ b/bsnes/ruby/input/rawinput.cpp @@ -291,12 +291,12 @@ public: wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hInstance = GetModuleHandle(0); wc.lpfnWndProc = RawInputWindowProc; - wc.lpszClassName = "RawInputClass"; + wc.lpszClassName = L"RawInputClass"; wc.lpszMenuName = 0; wc.style = CS_VREDRAW | CS_HREDRAW; RegisterClass(&wc); - hwnd = CreateWindow("RawInputClass", "RawInputClass", WS_POPUP, + hwnd = CreateWindow(L"RawInputClass", L"RawInputClass", WS_POPUP, 0, 0, 64, 64, 0, 0, GetModuleHandle(0), 0); //enumerate all HID devices diff --git a/bsnes/ruby/video/direct3d.cpp b/bsnes/ruby/video/direct3d.cpp index 8a5d49bd..86521884 100755 --- a/bsnes/ruby/video/direct3d.cpp +++ b/bsnes/ruby/video/direct3d.cpp @@ -346,17 +346,17 @@ public: for(unsigned i = 0; i < 256; i++) { char t[256]; sprintf(t, "d3dx9_%u.dll", i); - d3dx = LoadLibrary(t); + d3dx = LoadLibraryW(utf16_t(t)); if(d3dx) break; } - if(!d3dx) d3dx = LoadLibrary("d3dx9.dll"); + if(!d3dx) d3dx = LoadLibrary(L"d3dx9.dll"); if(!d3dx) return; EffectProc effectProc = (EffectProc)GetProcAddress(d3dx, "D3DXCreateEffect"); TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA"); LPD3DXBUFFER pBufferErrors = NULL; - effectProc(device, shaderSource, lstrlen(source), NULL, NULL, 0, NULL, &effect, &pBufferErrors); + effectProc(device, utf16_t(shaderSource), lstrlen(utf16_t(source)), NULL, NULL, 0, NULL, &effect, &pBufferErrors); D3DXHANDLE hTech; effect->FindNextValidTechnique(NULL, &hTech); diff --git a/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp b/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp index 36caaf17..06a5eb21 100755 --- a/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp +++ b/bsnes/snes/alt/ppu-performance/mmio/mmio.cpp @@ -6,8 +6,8 @@ void PPU::latch_counters() { regs.counters_latched = true; } -bool PPU::interlace() const { return regs.interlace; } -bool PPU::overscan() const { return regs.overscan; } +bool PPU::interlace() const { return display.interlace; } +bool PPU::overscan() const { return display.overscan; } bool PPU::hires() const { return regs.pseudo_hires || regs.bgmode == 5 || regs.bgmode == 6; } uint16 PPU::get_vram_addr() { diff --git a/bsnes/snes/alt/ppu-performance/ppu.cpp b/bsnes/snes/alt/ppu-performance/ppu.cpp index 82e37544..8b57ed29 100755 --- a/bsnes/snes/alt/ppu-performance/ppu.cpp +++ b/bsnes/snes/alt/ppu-performance/ppu.cpp @@ -81,6 +81,8 @@ void PPU::scanline() { void PPU::frame() { oam.frame(); system.frame(); + display.interlace = regs.interlace; + display.overscan = regs.overscan; display.framecounter = display.frameskip == 0 ? 0 : (display.framecounter + 1) % display.frameskip; } @@ -96,6 +98,8 @@ void PPU::reset() { PPUcounter::reset(); memset(surface, 0, 512 * 512 * sizeof(uint16)); mmio_reset(); + display.interlace = false; + display.overscan = false; } void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) { diff --git a/bsnes/snes/alt/ppu-performance/ppu.hpp b/bsnes/snes/alt/ppu-performance/ppu.hpp index d88e4e84..51c74a41 100755 --- a/bsnes/snes/alt/ppu-performance/ppu.hpp +++ b/bsnes/snes/alt/ppu-performance/ppu.hpp @@ -42,6 +42,8 @@ private: Screen screen; struct Display { + bool interlace; + bool overscan; unsigned width; unsigned height; unsigned frameskip; diff --git a/bsnes/snes/alt/ppu-performance/serialization.cpp b/bsnes/snes/alt/ppu-performance/serialization.cpp index 9e50b11d..90b182c6 100755 --- a/bsnes/snes/alt/ppu-performance/serialization.cpp +++ b/bsnes/snes/alt/ppu-performance/serialization.cpp @@ -24,6 +24,8 @@ void PPU::serialize(serializer &s) { oam.serialize(s); screen.serialize(s); + s.integer(display.interlace); + s.integer(display.overscan); s.integer(display.width); s.integer(display.height); diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 992d475b..7c0fcea5 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[] = "068.25"; + static const char Version[] = "069"; static const unsigned SerializerVersion = 13; } } diff --git a/bsnes/ui-phoenix/Makefile b/bsnes/ui-phoenix/Makefile index 2154a8c1..fb81f3ae 100755 --- a/bsnes/ui-phoenix/Makefile +++ b/bsnes/ui-phoenix/Makefile @@ -1,4 +1,4 @@ -ui_objects := ui-main ui-general ui-settings ui-tools ui-utility ui-cartridge +ui_objects := ui-main ui-general ui-settings ui-tools ui-input ui-utility ui-cartridge ui_objects += ruby phoenix ui_objects += $(if $(call streq,$(platform),win),resource) @@ -6,6 +6,8 @@ ui_objects += $(if $(call streq,$(platform),win),resource) ifeq ($(platform),x) flags += -DPHOENIX_GTK `pkg-config --cflags gtk+-2.0` link += `pkg-config --libs gtk+-2.0` +# flags += -DPHOENIX_QT `pkg-config --cflags QtCore QtGui` +# link += `pkg-config --libs QtCore QtGui` ruby := video.glx video.xv video.sdl ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao @@ -56,6 +58,7 @@ obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(u obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/general/*) obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/tools/*) obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/settings/*) +obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/input/*) obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/utility/*) obj/ui-cartridge.o: $(ui)/cartridge/cartridge.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/cartridge/*) diff --git a/bsnes/ui-phoenix/base.hpp b/bsnes/ui-phoenix/base.hpp index ddf3912b..3fe992c0 100755 --- a/bsnes/ui-phoenix/base.hpp +++ b/bsnes/ui-phoenix/base.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,7 @@ using namespace phoenix; #include "general/general.hpp" #include "settings/settings.hpp" #include "tools/tools.hpp" +#include "input/input.hpp" #include "utility/utility.hpp" #include "cartridge/cartridge.hpp" diff --git a/bsnes/ui-phoenix/cartridge/cartridge.cpp b/bsnes/ui-phoenix/cartridge/cartridge.cpp index 48eea227..35400c5e 100755 --- a/bsnes/ui-phoenix/cartridge/cartridge.cpp +++ b/bsnes/ui-phoenix/cartridge/cartridge.cpp @@ -3,18 +3,21 @@ Cartridge cartridge; bool Cartridge::loadNormal(const char *filename) { unload(); - if(loadCartridge(SNES::memory::cartrom, baseXML, baseName = filename) == false) return false; + if(loadCartridge(SNES::memory::cartrom, baseXML, filename) == false) return false; + baseName = nall::basename(filename); SNES::cartridge.load(SNES::Cartridge::Mode::Normal, lstring() << baseXML); loadMemory(SNES::memory::cartram, baseName, ".srm"); loadMemory(SNES::memory::cartrtc, baseName, ".rtc"); - utility.setTitle(notdir(nall::basename(baseName))); - cheatEditor.load(nall::basename(baseName)); + cheatEditor.load(baseName); + utility.setTitle(notdir(baseName)); + utility.showMessage(string("Loaded ", notdir(baseName))); + config.path.current = dir(baseName); return true; } void Cartridge::unload() { if(SNES::cartridge.loaded() == false) return; - cheatEditor.save(nall::basename(baseName)); + cheatEditor.save(baseName); saveMemory(SNES::memory::cartram, baseName, ".srm"); saveMemory(SNES::memory::cartrtc, baseName, ".rtc"); SNES::cartridge.unload(); @@ -42,7 +45,7 @@ bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char * bool Cartridge::loadMemory(SNES::MappedRAM &memory, string filename, const char *extension) { if(memory.size() == 0 || memory.size() == ~0) return true; - filename = string(nall::basename(filename), extension); + filename = string(filename, extension); if(file::exists(filename) == false) return false; file fp; if(fp.open(filename, file::mode_read)) { @@ -54,7 +57,7 @@ bool Cartridge::loadMemory(SNES::MappedRAM &memory, string filename, const char bool Cartridge::saveMemory(SNES::MappedRAM &memory, string filename, const char *extension) { if(memory.size() == 0 || memory.size() == ~0) return true; - filename = string(nall::basename(filename), extension); + filename = string(filename, extension); file fp; if(fp.open(filename, file::mode_write) == false) return false; fp.write(memory.data(), memory.size()); diff --git a/bsnes/ui-phoenix/cartridge/cartridge.hpp b/bsnes/ui-phoenix/cartridge/cartridge.hpp index b27a4400..fccd350b 100755 --- a/bsnes/ui-phoenix/cartridge/cartridge.hpp +++ b/bsnes/ui-phoenix/cartridge/cartridge.hpp @@ -2,10 +2,10 @@ struct Cartridge { bool loadNormal(const char *filename); void unload(); -private: string baseName, slotAName, slotBName; string baseXML, slotAXML, slotBXML; +private: bool loadCartridge(SNES::MappedRAM &memory, string &XML, const char *filename); bool loadMemory(SNES::MappedRAM &memory, string filename, const char *extension); bool saveMemory(SNES::MappedRAM &memory, string filename, const char *extension); diff --git a/bsnes/ui-phoenix/config.cpp b/bsnes/ui-phoenix/config.cpp index fc8ab1a0..4644b87c 100755 --- a/bsnes/ui-phoenix/config.cpp +++ b/bsnes/ui-phoenix/config.cpp @@ -5,10 +5,13 @@ void Configuration::load() { } void Configuration::save() { + mkdir(path.user, 0755); configuration::save(string(path.user, "bsnes-phoenix.cfg")); } void Configuration::create() { + attach(path.current = "", "path.current"); + attach(video.driver = "", "video.driver"); attach(video.synchronize = false, "video.synchronize"); attach(video.contrast = 100, "video.contrast"); @@ -23,4 +26,5 @@ void Configuration::create() { attach(input.driver = "", "input.driver"); attach(settings.focusPolicy = 0, "settings.focusPolicy"); + attach(settings.useNativeDialogs = false, "settings.useNativeDialogs"); } diff --git a/bsnes/ui-phoenix/config.hpp b/bsnes/ui-phoenix/config.hpp index 91548130..9fed046d 100755 --- a/bsnes/ui-phoenix/config.hpp +++ b/bsnes/ui-phoenix/config.hpp @@ -2,6 +2,7 @@ struct Configuration : public configuration { struct Path { string base; string user; + string current; } path; struct Video { @@ -25,6 +26,7 @@ struct Configuration : public configuration { struct Settings { unsigned focusPolicy; + bool useNativeDialogs; } settings; void load(); diff --git a/bsnes/ui-phoenix/general/file-browser.cpp b/bsnes/ui-phoenix/general/file-browser.cpp new file mode 100755 index 00000000..4f4e37b1 --- /dev/null +++ b/bsnes/ui-phoenix/general/file-browser.cpp @@ -0,0 +1,68 @@ +FileBrowser fileBrowser; + +void FileBrowser::create() { + application.windows.append(this); + Window::create(0, 0, 256, 256, "Load Cartridge"); + setDefaultFont(application.proportionalFont); + + unsigned x = 5, y = 5; + + unsigned height = Style::EditBoxHeight; + pathBox.create(*this, x, y, 630 - height - height - 10, height); + browseButton.create(*this, x + 630 - height - height - 5, y, height, height, "..."); + upButton.create(*this, x + 630 - height, y, height, height, ".."); y += height + 5; + + contentsBox.create(*this, x, y, 630, 350); y += 350 + 5; + + setGeometry(160, 160, 640, y); + + browseButton.onTick = { &FileBrowser::folderBrowse, this }; + upButton.onTick = { &FileBrowser::folderUp, this }; + contentsBox.onActivate = { &FileBrowser::fileActivate, this }; +} + +void FileBrowser::fileOpen(const char *pathname) { + setVisible(false); + setFolder(pathname); + setVisible(true); + contentsBox.setFocused(); +} + +void FileBrowser::setFolder(const char *pathname) { + contentsBox.reset(); + contents.reset(); + + folder = pathname; + folder.transform("\\", "/"); + folder.rtrim("/"); + pathBox.setText(folder); + lstring contentsList = directory::contents(folder); + foreach(item, contentsList) { + if(strend(item, "/") || strend(item, ".sfc")) contents.append(item); + } + foreach(item, contents) contentsBox.addItem(item); + contentsBox.setSelection(0); +} + +void FileBrowser::folderBrowse() { + string pathname = os.folderSelect(*this, folder); + if(pathname != "") setFolder(pathname); +} + +void FileBrowser::folderUp() { + setFolder(dir(folder)); +} + +void FileBrowser::fileActivate() { + if(auto position = contentsBox.selection()) { + string filename = contents[position()]; + if(strend(filename, "/")) { + setFolder(string(folder, "/", filename)); + } else { + filename = string(folder, "/", filename); + cartridge.loadNormal(filename); + SNES::system.power(); + setVisible(false); + } + } +} diff --git a/bsnes/ui-phoenix/general/file-browser.hpp b/bsnes/ui-phoenix/general/file-browser.hpp new file mode 100755 index 00000000..5dd3594d --- /dev/null +++ b/bsnes/ui-phoenix/general/file-browser.hpp @@ -0,0 +1,20 @@ +struct FileBrowser : Window { + TextBox pathBox; + Button browseButton; + Button upButton; + ListBox contentsBox; + + void fileOpen(const char *pathname); + void create(); + +private: + string folder; + lstring contents; + + void folderBrowse(); + void folderUp(); + void fileActivate(); + void setFolder(const char *pathname); +}; + +extern FileBrowser fileBrowser; diff --git a/bsnes/ui-phoenix/general/general.cpp b/bsnes/ui-phoenix/general/general.cpp index 1d067ea8..1c06a519 100755 --- a/bsnes/ui-phoenix/general/general.cpp +++ b/bsnes/ui-phoenix/general/general.cpp @@ -1,2 +1,3 @@ #include "../base.hpp" #include "main-window.cpp" +#include "file-browser.cpp" diff --git a/bsnes/ui-phoenix/general/general.hpp b/bsnes/ui-phoenix/general/general.hpp index 9f5a58c7..737238df 100755 --- a/bsnes/ui-phoenix/general/general.hpp +++ b/bsnes/ui-phoenix/general/general.hpp @@ -1 +1,2 @@ #include "main-window.hpp" +#include "file-browser.hpp" diff --git a/bsnes/ui-phoenix/general/main-window.cpp b/bsnes/ui-phoenix/general/main-window.cpp index f7572c78..639ea249 100755 --- a/bsnes/ui-phoenix/general/main-window.cpp +++ b/bsnes/ui-phoenix/general/main-window.cpp @@ -2,7 +2,7 @@ MainWindow mainWindow; void MainWindow::create() { application.windows.append(this); - Window::create(120, 120, 595, 448, string(SNES::Info::Name, " v", SNES::Info::Version)); + Window::create(128, 128, 595, 448, string(SNES::Info::Name, " v", SNES::Info::Version)); setDefaultFont(application.proportionalFont); setFont(application.proportionalFontBold); setBackgroundColor(0, 0, 0); @@ -21,12 +21,27 @@ void MainWindow::create() { settingsMuteAudio.setChecked(config.audio.mute); settingsSeparator.create(settings); settingsVideo.create(settings, "Video Settings ..."); + settingsInput.create(settings, "Input Settings ..."); settingsAdvanced.create(settings, "Advanced Settings ..."); tools.create(*this, "Tools"); + toolsStateSave.create(tools, "Save State"); + toolsStateSave1.create(toolsStateSave, "Slot 1"); + toolsStateSave2.create(toolsStateSave, "Slot 2"); + toolsStateSave3.create(toolsStateSave, "Slot 3"); + toolsStateSave4.create(toolsStateSave, "Slot 4"); + toolsStateSave5.create(toolsStateSave, "Slot 5"); + toolsStateLoad.create(tools, "Load State"); + toolsStateLoad1.create(toolsStateLoad, "Slot 1"); + toolsStateLoad2.create(toolsStateLoad, "Slot 2"); + toolsStateLoad3.create(toolsStateLoad, "Slot 3"); + toolsStateLoad4.create(toolsStateLoad, "Slot 4"); + toolsStateLoad5.create(toolsStateLoad, "Slot 5"); + toolsSeparator.create(tools); toolsCheatEditor.create(tools, "Cheat Editor ..."); help.create(*this, "Help"); + helpAbout.create(help, "About ..."); viewport.create(*this, 0, 0, 595, 448); utility.setStatus(""); @@ -37,9 +52,7 @@ void MainWindow::create() { utility.loadCartridgeNormal(); }; - systemQuit.onTick = []() { - application.quit = true; - }; + systemQuit.onTick = []() { application.quit = true; }; settingsSynchronizeVideo.onTick = []() { config.video.synchronize = mainWindow.settingsSynchronizeVideo.checked(); @@ -51,20 +64,34 @@ void MainWindow::create() { audio.set(Audio::Synchronize, config.audio.synchronize); }; - settingsMuteAudio.onTick = []() { - config.audio.mute = mainWindow.settingsMuteAudio.checked(); - }; + settingsMuteAudio.onTick = []() { config.audio.mute = mainWindow.settingsMuteAudio.checked(); }; - settingsVideo.onTick = []() { - videoSettingsWindow.setVisible(); - }; + settingsVideo.onTick = []() { videoSettings.setVisible(); }; + settingsInput.onTick = []() { inputSettings.setVisible(); }; + settingsAdvanced.onTick = []() { advancedSettings.setVisible(); }; - settingsAdvanced.onTick = []() { - advancedSettingsWindow.setVisible(); - }; + toolsStateSave1.onTick = []() { utility.saveState(1); }; + toolsStateSave2.onTick = []() { utility.saveState(2); }; + toolsStateSave3.onTick = []() { utility.saveState(3); }; + toolsStateSave4.onTick = []() { utility.saveState(4); }; + toolsStateSave5.onTick = []() { utility.saveState(5); }; - toolsCheatEditor.onTick = []() { - cheatEditor.setVisible(); + toolsStateLoad1.onTick = []() { utility.loadState(1); }; + toolsStateLoad2.onTick = []() { utility.loadState(2); }; + toolsStateLoad3.onTick = []() { utility.loadState(3); }; + toolsStateLoad4.onTick = []() { utility.loadState(4); }; + toolsStateLoad5.onTick = []() { utility.loadState(5); }; + + toolsCheatEditor.onTick = []() { cheatEditor.setVisible(); }; + + helpAbout.onTick = []() { + MessageWindow::information(mainWindow, string( + "bsnes\n\n", + "Version: ", SNES::Info::Version, "\n", + "Profile: ", SNES::Info::Profile, "\n", + "Author: byuu\n", + "Homepage: http://byuu.org/" + )); }; onClose = []() { diff --git a/bsnes/ui-phoenix/general/main-window.hpp b/bsnes/ui-phoenix/general/main-window.hpp index 8ca3b99a..50b0cbd1 100755 --- a/bsnes/ui-phoenix/general/main-window.hpp +++ b/bsnes/ui-phoenix/general/main-window.hpp @@ -9,10 +9,25 @@ struct MainWindow : Window { MenuCheckItem settingsMuteAudio; MenuSeparator settingsSeparator; MenuItem settingsVideo; + MenuItem settingsInput; MenuItem settingsAdvanced; Menu tools; + Menu toolsStateSave; + MenuItem toolsStateSave1; + MenuItem toolsStateSave2; + MenuItem toolsStateSave3; + MenuItem toolsStateSave4; + MenuItem toolsStateSave5; + Menu toolsStateLoad; + MenuItem toolsStateLoad1; + MenuItem toolsStateLoad2; + MenuItem toolsStateLoad3; + MenuItem toolsStateLoad4; + MenuItem toolsStateLoad5; + MenuSeparator toolsSeparator; MenuItem toolsCheatEditor; Menu help; + MenuItem helpAbout; Viewport viewport; void create(); diff --git a/bsnes/ui-phoenix/input/input.cpp b/bsnes/ui-phoenix/input/input.cpp new file mode 100755 index 00000000..eca7ee09 --- /dev/null +++ b/bsnes/ui-phoenix/input/input.cpp @@ -0,0 +1,208 @@ +#include "../base.hpp" +InputMapper inputMapper; + +void InputMapper::AbstractInput::bind() { + if(strend(mapping, ".Up")) type = Type::HatUp; + 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 type = Type::Button; + + string mappingValue = mapping; + if(auto position = strpos(mappingValue, ".")) mappingValue[position()] = 0; + scancode = Scancode::decode(mappingValue); +} + +int16_t InputMapper::DigitalInput::poll() { + int16_t value = inputMapper.state[inputMapper.activeState][scancode]; + switch(type) { + case AbstractInput::Type::Button: return (bool)value; + case AbstractInput::Type::HatUp: return (bool)(value & Joypad::HatUp); + 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); + } +} + +void InputMapper::Gamepad::create(const char *deviceName, const char *configName) { + name = deviceName; + up.name = "Up"; down.name = "Down"; left.name = "Left"; right.name = "Right"; + b.name = "B"; a.name = "A"; y.name = "Y"; x.name = "X"; + l.name = "L"; r.name = "R"; select.name = "Select"; start.name = "Start"; + append(&up); append(&down); append(&left); append(&right); + append(&b); append(&a); append(&y); append(&x); + append(&l); append(&r); append(&select); append(&start); + + config.attach(up.mapping = "", string("input.", configName, ".up")); + config.attach(down.mapping = "", string("input.", configName, ".down")); + config.attach(left.mapping = "", string("input.", configName, ".left")); + config.attach(right.mapping = "", string("input.", configName, ".right")); + config.attach(b.mapping = "", string("input.", configName, ".b")); + config.attach(a.mapping = "", string("input.", configName, ".a")); + config.attach(y.mapping = "", string("input.", configName, ".y")); + config.attach(x.mapping = "", string("input.", configName, ".x")); + config.attach(l.mapping = "", string("input.", configName, ".l")); + config.attach(r.mapping = "", string("input.", configName, ".r")); + config.attach(select.mapping = "", string("input.", configName, ".select")); + config.attach(start.mapping = "", string("input.", configName, ".start")); + + if(!strcmp(configName, "port1.gamepad")) { + up.mapping = "KB0::Up"; + down.mapping = "KB0::Down"; + left.mapping = "KB0::Left"; + right.mapping = "KB0::Right"; + b.mapping = "KB0::Z"; + a.mapping = "KB0::X"; + y.mapping = "KB0::A"; + x.mapping = "KB0::S"; + l.mapping = "KB0::D"; + r.mapping = "KB0::C"; + select.mapping = "KB0::Apostrophe"; + start.mapping = "KB0::Return"; + } +} + +int16_t InputMapper::Gamepad::poll(unsigned id) { + switch(id) { + case SNES::Input::JoypadID::Up: return up.poll(); + case SNES::Input::JoypadID::Down: return down.poll() & !up.poll(); + case SNES::Input::JoypadID::Left: return left.poll(); + case SNES::Input::JoypadID::Right: return right.poll() & !left.poll(); + case SNES::Input::JoypadID::B: return b.poll(); + case SNES::Input::JoypadID::A: return a.poll(); + case SNES::Input::JoypadID::Y: return y.poll(); + case SNES::Input::JoypadID::X: return x.poll(); + case SNES::Input::JoypadID::L: return l.poll(); + case SNES::Input::JoypadID::R: return r.poll(); + case SNES::Input::JoypadID::Select: return select.poll(); + case SNES::Input::JoypadID::Start: return start.poll(); + } + return 0; +} + +void InputMapper::Mouse::create(const char *deviceName, const char *configName) { + name = deviceName; + x.name = "X-axis"; y.name = "Y-axis"; + left.name = "Left Button"; right.name = "Right Button"; + append(&x); append(&y); + append(&left); append(&right); + + config.attach(x.mapping = "", string("input.", configName, ".x")); + config.attach(y.mapping = "", string("input.", configName, ".y")); + config.attach(left.mapping = "", string("input.", configName, ".left")); + config.attach(right.mapping = "", string("input.", configName, ".right")); + + x.mapping = "MS0::Xaxis"; + y.mapping = "MS0::Yaxis"; + left.mapping = "MS0::Button0"; + right.mapping = "MS0::Button2"; +} + +void InputMapper::SuperScope::create(const char *deviceName, const char *configName) { + name = deviceName; + x.name = "X-axis"; y.name = "Y-axis"; + trigger.name = "Trigger"; cursor.name = "Cursor"; turbo.name = "Turbo"; pause.name = "Pause"; + append(&x); append(&y); + append(&trigger); append(&cursor); append(&turbo); append(&pause); + + config.attach(x.mapping = "", string("input.", configName, ".x")); + config.attach(y.mapping = "", string("input.", configName, ".y")); + config.attach(trigger.mapping = "", string("input.", configName, ".trigger")); + config.attach(cursor.mapping = "", string("input.", configName, ".cursor")); + config.attach(turbo.mapping = "", string("input.", configName, ".turbo")); + config.attach(pause.mapping = "", string("input.", configName, ".pause")); + + x.mapping = "MS0::Xaxis"; + y.mapping = "MS0::Yaxis"; + trigger.mapping = "MS0::Button0"; + cursor.mapping = "MS0::Button2"; + turbo.mapping = "KB0::T"; + pause.mapping = "KB0::P"; +} + +void InputMapper::Justifier::create(const char *deviceName, const char *configName) { + name = deviceName; + x.name = "X-axis"; y.name = "Y-axis"; + trigger.name = "Trigger"; start.name = "Start"; + append(&x); append(&y); + append(&trigger); append(&start); + + config.attach(x.mapping = "", string("input.", configName, ".x")); + config.attach(y.mapping = "", string("input.", configName, ".y")); + config.attach(trigger.mapping = "", string("input.", configName, ".trigger")); + config.attach(start.mapping = "", string("input.", configName, ".start")); + + if(!strcmp(configName, "port2.justifierA")) { + x.mapping = "MS0::Xaxis"; + y.mapping = "MS0::Yaxis"; + trigger.mapping = "MS0::Button0"; + start.mapping = "MS0::Button2"; + } +} + +void InputMapper::create() { + activeState = 0; + + port1.name = "Controller Port 1"; + port1.gamepad.create("Gamepad", "port1.gamepad"); + port1.multitapA.create("Multitap - Port 1", "port1.multitapA"); + port1.multitapB.create("Multitap - Port 2", "port1.multitapB"); + port1.multitapC.create("Multitap - Port 3", "port1.multitapC"); + port1.multitapD.create("Multitap - Port 4", "port1.multitapD"); + port1.mouse.create("Mouse", "port1.mouse"); + port1.append(&port1.gamepad); + port1.append(&port1.multitapA); + port1.append(&port1.multitapB); + port1.append(&port1.multitapC); + port1.append(&port1.multitapD); + port1.append(&port1.mouse); + + port2.name = "Controller Port 2"; + port2.gamepad.create("Gamepad", "port2.gamepad"); + port2.multitapA.create("Multitap - Port 1", "port2.multitapA"); + port2.multitapB.create("Multitap - Port 2", "port2.multitapB"); + port2.multitapC.create("Multitap - Port 3", "port2.multitapC"); + port2.multitapD.create("Multitap - Port 4", "port2.multitapD"); + port2.mouse.create("Mouse", "port2.mouse"); + port2.superScope.create("Super Scope", "port2.superScope"); + port2.justifierA.create("Justifier - Port 1", "port2.justifierA"); + port2.justifierB.create("Justifier - Port 2", "port2.justifierB"); + port2.append(&port2.gamepad); + port2.append(&port2.multitapA); + port2.append(&port2.multitapB); + port2.append(&port2.multitapC); + port2.append(&port2.multitapD); + port2.append(&port2.mouse); + port2.append(&port2.superScope); + port2.append(&port2.justifierA); + port2.append(&port2.justifierB); +} + +void InputMapper::bind() { + for(unsigned i = 0; i < port1.size(); i++) { + Controller &controller = *port1[i]; + for(unsigned n = 0; n < controller.size(); n++) controller[n]->bind(); + } + for(unsigned i = 0; i < port2.size(); i++) { + Controller &controller = *port2[i]; + for(unsigned n = 0; n < controller.size(); n++) controller[n]->bind(); + } +} + +void InputMapper::poll() { + activeState ^= 1; + input.poll(state[activeState]); + + for(unsigned i = 0; i < Scancode::Limit; i++) { + if(state[0][i] != state[1][i]) { + inputSettings.inputEvent(i, state[activeState][i]); + } + } +} + +int16_t InputMapper::poll(bool port, SNES::Input::Device device, unsigned index, unsigned id) { + if(port == 0) { + if(device == SNES::Input::Device::Joypad) return port1.gamepad.poll(id); + } + return 0; +} diff --git a/bsnes/ui-phoenix/input/input.hpp b/bsnes/ui-phoenix/input/input.hpp new file mode 100755 index 00000000..351d6d60 --- /dev/null +++ b/bsnes/ui-phoenix/input/input.hpp @@ -0,0 +1,81 @@ +struct InputMapper { + struct AbstractInput { + enum class Type : unsigned { Button, HatUp, HatDown, HatLeft, HatRight } type; + string name; + string mapping; + unsigned scancode; + virtual void bind(); + }; + + struct AnalogInput : AbstractInput { + }; + + struct DigitalInput : AbstractInput { + int16_t poll(); + }; + + struct Controller : array { + string name; + }; + + struct Gamepad : Controller { + DigitalInput up, down, left, right; + DigitalInput b, a, y, x; + DigitalInput l, r, select, start; + void create(const char *deviceName, const char *configName); + int16_t poll(unsigned index); + }; + + struct Mouse : Controller { + AnalogInput x, y; + DigitalInput left, right; + void create(const char *deviceName, const char *configName); + }; + + struct SuperScope : Controller { + AnalogInput x, y; + DigitalInput trigger, cursor, turbo, pause; + void create(const char *deviceName, const char *configName); + }; + + struct Justifier : Controller { + AnalogInput x, y; + DigitalInput trigger, start; + void create(const char *deviceName, const char *configName); + }; + + struct ControllerPort : array { + string name; + }; + + struct Port1 : ControllerPort { + Gamepad gamepad; + Gamepad multitapA; + Gamepad multitapB; + Gamepad multitapC; + Gamepad multitapD; + Mouse mouse; + } port1; + + struct Port2 : ControllerPort { + Gamepad gamepad; + Gamepad multitapA; + Gamepad multitapB; + Gamepad multitapC; + Gamepad multitapD; + Mouse mouse; + SuperScope superScope; + Justifier justifierA; + Justifier justifierB; + } port2; + + int16_t state[2][Scancode::Limit]; + bool activeState; + + void create(); + void bind(); + void poll(); + int16_t poll(bool port, SNES::Input::Device device, unsigned index, unsigned id); +}; + +extern InputMapper inputMapper; diff --git a/bsnes/ui-phoenix/interface.cpp b/bsnes/ui-phoenix/interface.cpp index 27ed0834..e4790d99 100755 --- a/bsnes/ui-phoenix/interface.cpp +++ b/bsnes/ui-phoenix/interface.cpp @@ -99,30 +99,9 @@ void Interface::audio_sample(uint16_t left, uint16_t right) { } void Interface::input_poll() { - input.poll(state); } int16_t Interface::input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id) { - //ignore input when main window is not active? if(config.settings.focusPolicy == 1 && mainWindow.focused() == false) return 0; - - if(port == 0) { - if(device == SNES::Input::Device::Joypad) { - switch(id) { - case SNES::Input::JoypadID::Up: return state[keyboard(0)[Keyboard::Up]]; - case SNES::Input::JoypadID::Down: return state[keyboard(0)[Keyboard::Down]]; - case SNES::Input::JoypadID::Left: return state[keyboard(0)[Keyboard::Left]]; - case SNES::Input::JoypadID::Right: return state[keyboard(0)[Keyboard::Right]]; - case SNES::Input::JoypadID::B: return state[keyboard(0)[Keyboard::Z]]; - case SNES::Input::JoypadID::A: return state[keyboard(0)[Keyboard::X]]; - case SNES::Input::JoypadID::Y: return state[keyboard(0)[Keyboard::A]]; - case SNES::Input::JoypadID::X: return state[keyboard(0)[Keyboard::S]]; - case SNES::Input::JoypadID::L: return state[keyboard(0)[Keyboard::D]]; - case SNES::Input::JoypadID::R: return state[keyboard(0)[Keyboard::C]]; - case SNES::Input::JoypadID::Select: return state[keyboard(0)[Keyboard::Apostrophe]]; - case SNES::Input::JoypadID::Start: return state[keyboard(0)[Keyboard::Return]]; - } - } - } - return 0; + return inputMapper.poll(port, device, index, id); } diff --git a/bsnes/ui-phoenix/interface.hpp b/bsnes/ui-phoenix/interface.hpp index e1d54ea1..7421f883 100755 --- a/bsnes/ui-phoenix/interface.hpp +++ b/bsnes/ui-phoenix/interface.hpp @@ -8,7 +8,6 @@ struct Palette { }; struct Interface : public SNES::Interface { - int16_t state[Scancode::Limit]; void video_refresh(const uint16_t *data, unsigned width, unsigned height); void audio_sample(uint16_t left, uint16_t right); void input_poll(); diff --git a/bsnes/ui-phoenix/main.cpp b/bsnes/ui-phoenix/main.cpp index 8796734b..b24013ff 100755 --- a/bsnes/ui-phoenix/main.cpp +++ b/bsnes/ui-phoenix/main.cpp @@ -4,8 +4,11 @@ Application application; void Application::main(int argc, char **argv) { - initialize_arguments(argc, argv); + #if defined(PLATFORM_WIN) + utf8_args(argc, argv); + #endif config.create(); + inputMapper.create(); char temp[PATH_MAX]; config.path.base = realpath(argv[0], temp); @@ -17,6 +20,8 @@ void Application::main(int argc, char **argv) { config.path.user.append(".bsnes/"); config.load(); config.save(); + if(config.path.current == "") config.path.current = config.path.base; + inputMapper.bind(); #if defined(PHOENIX_WINDOWS) proportionalFont.create("Tahoma", 8); @@ -28,15 +33,20 @@ void Application::main(int argc, char **argv) { monospaceFont.create("Liberation Mono", 8); #endif + if(config.video.driver == "") config.video.driver = video.default_driver(); + if(config.audio.driver == "") config.audio.driver = audio.default_driver(); + if(config.input.driver == "") config.input.driver = video.default_driver(); + palette.update(); mainWindow.create(); - videoSettingsWindow.create(); - advancedSettingsWindow.create(); + fileBrowser.create(); + videoSettings.create(); + inputSettings.create(); + advancedSettings.create(); cheatEditor.create(); mainWindow.setVisible(); - while(os.pending()) os.run(); + os.run(); - if(config.video.driver == "") config.video.driver = video.default_driver(); video.driver(config.video.driver); video.set(Video::Handle, mainWindow.viewport.handle()); video.set(Video::Synchronize, config.video.synchronize); @@ -47,7 +57,6 @@ void Application::main(int argc, char **argv) { video.init(); } - if(config.audio.driver == "") config.audio.driver = audio.default_driver(); audio.driver(config.audio.driver); audio.set(Audio::Handle, mainWindow.viewport.handle()); audio.set(Audio::Synchronize, config.audio.synchronize); @@ -58,7 +67,6 @@ void Application::main(int argc, char **argv) { audio.init(); } - if(config.input.driver == "") config.input.driver = video.default_driver(); input.driver(config.input.driver); input.set(Input::Handle, mainWindow.viewport.handle()); if(input.init() == false) { @@ -74,7 +82,9 @@ void Application::main(int argc, char **argv) { } while(quit == false) { - while(os.pending()) os.run(); + os.run(); + inputMapper.poll(); + utility.updateStatus(); if(SNES::cartridge.loaded()) { //pause emulator when main window is inactive? @@ -92,7 +102,7 @@ void Application::main(int argc, char **argv) { cartridge.unload(); foreach(window, windows) window->setVisible(false); - while(os.pending()) os.run(); + os.run(); SNES::system.term(); config.save(); diff --git a/bsnes/ui-phoenix/settings/advanced.cpp b/bsnes/ui-phoenix/settings/advanced.cpp index 07bd5dad..040b3cdf 100755 --- a/bsnes/ui-phoenix/settings/advanced.cpp +++ b/bsnes/ui-phoenix/settings/advanced.cpp @@ -1,6 +1,6 @@ -AdvancedSettingsWindow advancedSettingsWindow; +AdvancedSettings advancedSettings; -void AdvancedSettingsWindow::create() { +void AdvancedSettings::create() { application.windows.append(this); Window::create(0, 0, 256, 256, "Advanced Settings"); setDefaultFont(application.proportionalFont); @@ -23,12 +23,17 @@ void AdvancedSettingsWindow::create() { focusPolicyPause.create(*this, x, y, 195, Style::CheckBoxHeight, "Pause emulator when inactive"); focusPolicyIgnore.create(focusPolicyPause, x + 200, y, 195, Style::CheckBoxHeight, "Ignore input when inactive"); focusPolicyAllow.create(focusPolicyPause, x + 400, y, 195, Style::CheckBoxHeight, "Always allow input"); y += Style::CheckBoxHeight + 5; - if(config.settings.focusPolicy == 0) focusPolicyPause.setChecked(); if(config.settings.focusPolicy == 1) focusPolicyIgnore.setChecked(); if(config.settings.focusPolicy == 2) focusPolicyAllow.setChecked(); - setGeometry(0, 0, 605, y); + miscellaneousLabel.create(*this, x, y, 595, Style::LabelHeight, "Miscellaneous :."); y += Style::LabelHeight + 5; + miscellaneousLabel.setFont(application.proportionalFontBold); + + useNativeDialogs.create(*this, x, y, 595, Style::CheckBoxHeight, "Use native OS dialogs"); y += Style::CheckBoxHeight + 5; + useNativeDialogs.setChecked(config.settings.useNativeDialogs); + + setGeometry(160, 160, 605, y); lstring list; @@ -53,22 +58,24 @@ void AdvancedSettingsWindow::create() { videoDriverBox.onChange = []() { lstring list; list.split(";", video.driver_list()); - config.video.driver = list[advancedSettingsWindow.videoDriverBox.selection()]; + config.video.driver = list[advancedSettings.videoDriverBox.selection()]; }; audioDriverBox.onChange = []() { lstring list; list.split(";", audio.driver_list()); - config.audio.driver = list[advancedSettingsWindow.audioDriverBox.selection()]; + config.audio.driver = list[advancedSettings.audioDriverBox.selection()]; }; inputDriverBox.onChange = []() { lstring list; list.split(";", input.driver_list()); - config.input.driver = list[advancedSettingsWindow.inputDriverBox.selection()]; + config.input.driver = list[advancedSettings.inputDriverBox.selection()]; }; focusPolicyPause.onTick = []() { config.settings.focusPolicy = 0; }; focusPolicyIgnore.onTick = []() { config.settings.focusPolicy = 1; }; focusPolicyAllow.onTick = []() { config.settings.focusPolicy = 2; }; + + useNativeDialogs.onTick = []() { config.settings.useNativeDialogs = advancedSettings.useNativeDialogs.checked(); }; } diff --git a/bsnes/ui-phoenix/settings/advanced.hpp b/bsnes/ui-phoenix/settings/advanced.hpp index 9bbc8cfa..11def15c 100755 --- a/bsnes/ui-phoenix/settings/advanced.hpp +++ b/bsnes/ui-phoenix/settings/advanced.hpp @@ -1,4 +1,4 @@ -struct AdvancedSettingsWindow : Window { +struct AdvancedSettings : Window { Label driverSelectionLabel; Label videoDriverLabel; ComboBox videoDriverBox; @@ -10,8 +10,10 @@ struct AdvancedSettingsWindow : Window { RadioBox focusPolicyPause; RadioBox focusPolicyIgnore; RadioBox focusPolicyAllow; + Label miscellaneousLabel; + CheckBox useNativeDialogs; void create(); }; -extern AdvancedSettingsWindow advancedSettingsWindow; +extern AdvancedSettings advancedSettings; diff --git a/bsnes/ui-phoenix/settings/input.cpp b/bsnes/ui-phoenix/settings/input.cpp new file mode 100755 index 00000000..a64e5838 --- /dev/null +++ b/bsnes/ui-phoenix/settings/input.cpp @@ -0,0 +1,111 @@ +InputSettings inputSettings; +static InputMapper::AbstractInput *activeInput = 0; + +void InputSettings::create() { + application.windows.append(this); + Window::create(0, 0, 256, 256, "Input Settings"); + setDefaultFont(application.proportionalFont); + setFont(application.proportionalFontBold); + setStatusVisible(); + + unsigned x = 5, y = 5; + + portLabel.create(*this, x, y, 50, Style::ComboBoxHeight, "Port:"); + portBox.create(*this, x + 50, y, 200, Style::ComboBoxHeight); + portBox.addItem(inputMapper.port1.name); + portBox.addItem(inputMapper.port2.name); + 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.setHeaderVisible(); + mappingList.setFocused(); + + setGeometry(160, 160, 515, y); + + portChanged(); + portBox.onChange = { &InputSettings::portChanged, this }; + deviceBox.onChange = { &InputSettings::deviceChanged, this }; + mappingList.onActivate = { &InputSettings::assignInput, this }; +} + +void InputSettings::portChanged() { + deviceBox.reset(); + InputMapper::ControllerPort &port = ( + portBox.selection() == 0 + ? (InputMapper::ControllerPort&)inputMapper.port1 + : (InputMapper::ControllerPort&)inputMapper.port2 + ); + + for(unsigned i = 0; i < port.size(); i++) { + deviceBox.addItem(port[i]->name); + } + deviceChanged(); +} + +void InputSettings::deviceChanged() { + mappingList.reset(); + InputMapper::ControllerPort &port = ( + portBox.selection() == 0 + ? (InputMapper::ControllerPort&)inputMapper.port1 + : (InputMapper::ControllerPort&)inputMapper.port2 + ); + InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()]; + + for(unsigned i = 0; i < controller.size(); i++) { + string mapping = controller[i]->mapping; + if(mapping == "") mapping = "None"; + mappingList.addItem(string(controller[i]->name, "\t", mapping)); + } + mappingList.resizeColumnsToContent(); +} + +void InputSettings::assignInput() { + if(auto position = mappingList.selection()) { + InputMapper::ControllerPort &port = ( + portBox.selection() == 0 + ? (InputMapper::ControllerPort&)inputMapper.port1 + : (InputMapper::ControllerPort&)inputMapper.port2 + ); + InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()]; + + portBox.setEnabled(false); + deviceBox.setEnabled(false); + mappingList.setEnabled(false); + inputMapper.poll(); //flush any pending keypresses + activeInput = controller[position()]; + setStatusText(string("Set assignment for [", activeInput->name, "] ...")); + } +} + +void InputSettings::setMapping(const char *mapping) { + activeInput->mapping = mapping; + activeInput = 0; + inputMapper.bind(); + setStatusText(""); + portBox.setEnabled(true); + deviceBox.setEnabled(true); + mappingList.setEnabled(true); + deviceChanged(); +} + +void InputSettings::inputEvent(uint16_t scancode, int16_t value) { + if(activeInput == 0) return; //not remapping any keys right now? + + string mapping = Scancode::encode(scancode); + if(auto position = strpos(mapping, "::Escape")) return setMapping(""); + + if(dynamic_cast(activeInput)) { + } else if(dynamic_cast(activeInput)) { + if(Keyboard::isAnyKey(scancode) && value) { + setMapping(mapping); + } else if(Joypad::isAnyHat(scancode) && value) { + if(value == Joypad::HatUp) setMapping(string(mapping, ".Up")); + 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::isAnyButton(scancode) && value) { + setMapping(mapping); + } + } +} diff --git a/bsnes/ui-phoenix/settings/input.hpp b/bsnes/ui-phoenix/settings/input.hpp new file mode 100755 index 00000000..10d3e0dc --- /dev/null +++ b/bsnes/ui-phoenix/settings/input.hpp @@ -0,0 +1,18 @@ +struct InputSettings : Window { + Label portLabel; + ComboBox portBox; + Label deviceLabel; + ComboBox deviceBox; + ListBox mappingList; + + void inputEvent(uint16_t scancode, int16_t value); + void create(); + +private: + void portChanged(); + void deviceChanged(); + void setMapping(const char *mapping); + void assignInput(); +}; + +extern InputSettings inputSettings; diff --git a/bsnes/ui-phoenix/settings/settings.cpp b/bsnes/ui-phoenix/settings/settings.cpp index b9eaee87..7cd1be29 100755 --- a/bsnes/ui-phoenix/settings/settings.cpp +++ b/bsnes/ui-phoenix/settings/settings.cpp @@ -1,3 +1,4 @@ #include "../base.hpp" #include "video.cpp" +#include "input.cpp" #include "advanced.cpp" diff --git a/bsnes/ui-phoenix/settings/settings.hpp b/bsnes/ui-phoenix/settings/settings.hpp index 456a376b..dee4e0e8 100755 --- a/bsnes/ui-phoenix/settings/settings.hpp +++ b/bsnes/ui-phoenix/settings/settings.hpp @@ -1,2 +1,3 @@ #include "video.hpp" +#include "input.hpp" #include "advanced.hpp" diff --git a/bsnes/ui-phoenix/settings/video.cpp b/bsnes/ui-phoenix/settings/video.cpp index 0b4e5764..bf36f077 100755 --- a/bsnes/ui-phoenix/settings/video.cpp +++ b/bsnes/ui-phoenix/settings/video.cpp @@ -1,6 +1,6 @@ -VideoSettingsWindow videoSettingsWindow; +VideoSettings videoSettings; -void VideoSettingsWindow::create() { +void VideoSettings::create() { application.windows.append(this); Window::create(0, 0, 256, 256, "Video Settings"); setDefaultFont(application.proportionalFont); @@ -24,7 +24,7 @@ void VideoSettingsWindow::create() { gammaRampCheck.create (*this, x, y, 430, 15, "Enable NTSC gamma ramp simulation"); y += 15; - setGeometry(0, 0, 440, y + 5); + setGeometry(160, 160, 440, y + 5); contrastSlider.setPosition(config.video.contrast); brightnessSlider.setPosition(config.video.brightness); @@ -32,10 +32,10 @@ void VideoSettingsWindow::create() { gammaRampCheck.setChecked(config.video.useGammaRamp); contrastSlider.onChange = brightnessSlider.onChange = gammaSlider.onChange = gammaRampCheck.onTick = - { &VideoSettingsWindow::adjust, this }; + { &VideoSettings::adjust, this }; } -void VideoSettingsWindow::adjust() { +void VideoSettings::adjust() { contrastValue.setText(string(contrastSlider.position(), "%")); brightnessValue.setText(string(brightnessSlider.position(), "%")); gammaValue.setText(string(gammaSlider.position(), "%")); diff --git a/bsnes/ui-phoenix/settings/video.hpp b/bsnes/ui-phoenix/settings/video.hpp index 8bb75bbf..fd946d7e 100755 --- a/bsnes/ui-phoenix/settings/video.hpp +++ b/bsnes/ui-phoenix/settings/video.hpp @@ -1,4 +1,4 @@ -struct VideoSettingsWindow : Window { +struct VideoSettings : Window { Label colorAdjustmentLabel; Label contrastLabel; Label contrastValue; @@ -15,4 +15,4 @@ struct VideoSettingsWindow : Window { void adjust(); }; -extern VideoSettingsWindow videoSettingsWindow; +extern VideoSettings videoSettings; diff --git a/bsnes/ui-phoenix/tools/cheat-editor.cpp b/bsnes/ui-phoenix/tools/cheat-editor.cpp index cf439ec9..23724797 100755 --- a/bsnes/ui-phoenix/tools/cheat-editor.cpp +++ b/bsnes/ui-phoenix/tools/cheat-editor.cpp @@ -69,7 +69,7 @@ void CheatEditor::create() { descLabel.create(*this, x, y, 80, Style::EditBoxHeight, "Description:"); descEdit.create (*this, x + 80, y, 420, Style::EditBoxHeight); y+= Style::EditBoxHeight + 5; - setGeometry(0, 0, 510, y); + setGeometry(160, 160, 510, y); synchronize(); cheatList.onActivate = { &CheatEditor::toggle, this }; diff --git a/bsnes/ui-phoenix/utility/utility.cpp b/bsnes/ui-phoenix/utility/utility.cpp index b5700559..dabc8975 100755 --- a/bsnes/ui-phoenix/utility/utility.cpp +++ b/bsnes/ui-phoenix/utility/utility.cpp @@ -9,15 +9,68 @@ void Utility::setTitle(const char *text) { } } +void Utility::updateStatus() { + time_t currentTime = time(0); + string text = ((currentTime - statusTime) > 3) ? statusText : statusMessage; + if(text != statusCurrentText) { + mainWindow.setStatusText(statusCurrentText = text); + } +} + void Utility::setStatus(const char *text) { static char profile[] = { '[', SNES::Info::Profile[0], ']', ' ', 0 }; - mainWindow.setStatusText(string(profile, text)); + statusText = string(profile, text); +} + +void Utility::showMessage(const char *text) { + statusMessage = text; + statusTime = time(0); } void Utility::loadCartridgeNormal() { - string filename = os.fileOpen(mainWindow, "SNES cartridges\t*.sfc\nAll files\t*", "/media/sdb1/root/snes_roms"); - if(filename != "") { - cartridge.loadNormal(filename); - SNES::system.power(); + if(config.settings.useNativeDialogs == false) { + fileBrowser.fileOpen(config.path.current); + } else { + string filename = os.fileOpen(mainWindow, "SNES cartridges\t*.sfc\nAll files\t*", config.path.current); + if(filename != "") { + cartridge.loadNormal(filename); + SNES::system.power(); + } } } + +void Utility::saveState(unsigned slot) { + string filename = { cartridge.baseName, "-", slot, ".bst" }; + SNES::system.runtosave(); + serializer s = SNES::system.serialize(); + file fp; + if(fp.open(filename, file::mode_write)) { + fp.write(s.data(), s.size()); + fp.close(); + showMessage(string("Saved state ", slot)); + } else { + showMessage(string("Failed to save state ", slot)); + } +} + +void Utility::loadState(unsigned slot) { + string filename = { cartridge.baseName, "-", slot, ".bst" }; + file fp; + if(fp.open(filename, file::mode_read)) { + unsigned size = fp.size(); + uint8_t *data = new uint8_t[size]; + fp.read(data, size); + fp.close(); + serializer s(data, size); + delete[] data; + if(SNES::system.unserialize(s) == true) { + showMessage(string("Loaded state ", slot)); + } else { + showMessage(string("Failed to load state ", slot)); + } + } +} + +Utility::Utility() { + statusTime = 0; +} diff --git a/bsnes/ui-phoenix/utility/utility.hpp b/bsnes/ui-phoenix/utility/utility.hpp index dda6efd1..d6879630 100755 --- a/bsnes/ui-phoenix/utility/utility.hpp +++ b/bsnes/ui-phoenix/utility/utility.hpp @@ -1,8 +1,20 @@ struct Utility { void setTitle(const char *text); + void updateStatus(); void setStatus(const char *text); + void showMessage(const char *text); void loadCartridgeNormal(); + void saveState(unsigned slot); + void loadState(unsigned slot); + + Utility(); + +private: + string statusCurrentText; + string statusText; + string statusMessage; + time_t statusTime; }; extern Utility utility; diff --git a/bsnes/ui-qt/application/application.cpp b/bsnes/ui-qt/application/application.cpp index 21fad73c..0566618c 100755 --- a/bsnes/ui-qt/application/application.cpp +++ b/bsnes/ui-qt/application/application.cpp @@ -67,9 +67,9 @@ int Application::main(int &argc, char **argv) { #else //Windows port uses 256x256 icon from resource file CoInitialize(0); + utf8_args(argc, argv); #endif - initialize_arguments(argc, argv); //ensure argv[]s are in UTF-8 format initPaths(argv[0]); locateFile(configFilename = "bsnes.cfg", true); locateFile(styleSheetFilename = "style.qss", false);