Update to v069 release.

byuu says (since v068):

- added new effect toggle tool window, which allows toggling of BG/OAM
  graphics layers and DSP audio channels
- added an option to use the native OS file and folder open dialogs
  instead of my custom browser
- added a new state selection window
- added frame skipping support, which is only used during fast
  forwarding; as a result, fast forward is now ~80% faster
- removed unnecessary icons, added workaround for checkbox/radiobox menu
  icons on Linux/GNOME
- added RTS/CTS support to serial simulation
- all cores: OAM high table even address writes should update OAM latch
  data register [blargg]
- accuracy core: major improvements to mosaic emulation
- accuracy core: added additional hardware-based caching, resulting in
  a ~15% speed boost
- accuracy core: emulated CGRAM address invalidation for writes during
  active display
- performance core: added new S-PPU renderer, resulting in a ~10% speed
  bost
This commit is contained in:
Tim Allen 2010-09-26 15:09:31 +10:00
parent 4525d00eba
commit ccfff86140
54 changed files with 1871 additions and 124 deletions

View File

@ -1,6 +1,6 @@
include nall/Makefile
snes := snes
profile := performance
profile := compatibility
ui := ui-qt
# compiler

View File

@ -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

129
bsnes/nall/directory.hpp Executable file
View File

@ -0,0 +1,129 @@
#ifndef NALL_DIRECTORY_HPP
#define NALL_DIRECTORY_HPP
#include <nall/foreach.hpp>
#include <nall/sort.hpp>
#include <nall/string.hpp>
#if defined(_WIN32)
#include <nall/utf8.hpp>
#else
#include <dirent.h>
#include <stdio.h>
#include <sys/types.h>
#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

View File

@ -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

View File

@ -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 <windows.h>
#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)

View File

@ -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() {

View File

@ -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);
}

View File

@ -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() {

View File

@ -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<bool ()> 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<void ()> 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<void ()> onActivate;
nall::function<void ()> 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();

View File

@ -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() {

View File

@ -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);

View File

@ -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;

View File

@ -39,9 +39,8 @@ bool OS::pending() {
return QApplication::hasPendingEvents();
}
bool OS::run() {
void OS::run() {
QApplication::processEvents();
return QApplication::hasPendingEvents();
}
void OS::main() {

View File

@ -125,6 +125,7 @@ struct Window : Widget {
nall::function<bool ()> 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();

925
bsnes/phoenix/qt/qt.moc Executable file
View File

@ -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 <QObject>."
#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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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<void*>(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

View File

@ -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);
}

View File

@ -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<ListBox*>(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<Window*>(object_ptr)) return DefWindowProc(hwnd, msg, wparam, lparam);

View File

@ -254,7 +254,7 @@ struct MessageWindow : Object {
struct OS : Object {
bool pending();
bool run();
void run();
void main();
void quit();
unsigned desktopWidth();

View File

@ -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

View File

@ -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);

View File

@ -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() {

View File

@ -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) {

View File

@ -42,6 +42,8 @@ private:
Screen screen;
struct Display {
bool interlace;
bool overscan;
unsigned width;
unsigned height;
unsigned frameskip;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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/*)

View File

@ -2,6 +2,7 @@
#include <nall/base64.hpp>
#include <nall/config.hpp>
#include <nall/directory.hpp>
#include <nall/input.hpp>
#include <nall/ups.hpp>
#include <nall/snes/info.hpp>
@ -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"

View File

@ -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());

View File

@ -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);

View File

@ -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");
}

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -1,2 +1,3 @@
#include "../base.hpp"
#include "main-window.cpp"
#include "file-browser.cpp"

View File

@ -1 +1,2 @@
#include "main-window.hpp"
#include "file-browser.hpp"

View File

@ -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 = []() {

View File

@ -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();

208
bsnes/ui-phoenix/input/input.cpp Executable file
View File

@ -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;
}

View File

@ -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<AbstractInput*> {
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<Controller*> {
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;

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -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(); };
}

View File

@ -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;

View File

@ -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<InputMapper::AnalogInput*>(activeInput)) {
} else if(dynamic_cast<InputMapper::DigitalInput*>(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);
}
}
}

View File

@ -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;

View File

@ -1,3 +1,4 @@
#include "../base.hpp"
#include "video.cpp"
#include "input.cpp"
#include "advanced.cpp"

View File

@ -1,2 +1,3 @@
#include "video.hpp"
#include "input.hpp"
#include "advanced.hpp"

View File

@ -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(), "%"));

View File

@ -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;

View File

@ -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 };

View File

@ -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;
}

View File

@ -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;

View File

@ -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);