From baccd4ef2f7e3b730c80c2a69edb92368ee5197c Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 11 Jan 2016 00:45:02 -0800 Subject: [PATCH 01/68] Qt: Fix some potential crashes with the gamepad mapping --- CHANGES | 1 + src/platform/qt/GBAKeyEditor.cpp | 2 +- src/platform/qt/InputController.cpp | 9 +++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 37fb3e7c3..6f344dbea 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ Bugfixes: - Util: Fix excessive memory allocation when decoding a PNG - GBA: Fix Iridion II savetype - Libretro: Fix aspect ratio + - Qt: Fix some potential crashes with the gamepad mapping Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index f8f901c77..f56c25535 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -280,7 +280,7 @@ void GBAKeyEditor::lookupAxes(const GBAInputMap* map) { void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, GBAKey key) { #ifdef BUILD_SDL - if (m_type == SDL_BINDING_BUTTON) { + if (m_type == SDL_BINDING_BUTTON && keyEditor->axis() >= 0) { m_controller->bindAxis(m_type, keyEditor->axis(), keyEditor->direction(), key); } #endif diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 023ad7568..a7b99ee8a 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -399,14 +399,19 @@ void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direct if (old) { description = *old; } + int deadzone = 0; + if (m_deadzones.size() > axis) { + deadzone = m_deadzones[axis]; + } switch (direction) { case GamepadAxisEvent::NEGATIVE: description.lowDirection = key; - description.deadLow = m_deadzones[axis] - AXIS_THRESHOLD; + + description.deadLow = deadzone - AXIS_THRESHOLD; break; case GamepadAxisEvent::POSITIVE: description.highDirection = key; - description.deadHigh = m_deadzones[axis] + AXIS_THRESHOLD; + description.deadHigh = deadzone + AXIS_THRESHOLD; break; default: return; From 2b5da04d9c5acf7ac152c903ac73d229ae79d343 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 11 Jan 2016 00:49:14 -0800 Subject: [PATCH 02/68] Qt: Begin settings view revamp --- CHANGES | 1 + src/platform/qt/GBAKeyEditor.cpp | 3 - src/platform/qt/SettingsView.cpp | 22 ++- src/platform/qt/SettingsView.h | 5 +- src/platform/qt/SettingsView.ui | 317 ++++++++++++++++--------------- src/platform/qt/Window.cpp | 39 +--- src/platform/qt/Window.h | 7 - 7 files changed, 188 insertions(+), 206 deletions(-) diff --git a/CHANGES b/CHANGES index 6f344dbea..60cb54149 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,7 @@ Features: - Libretro: Settings for using BIOS and skipping intro - Libretro: Customizable idle loop removal - Implemented cycle counting for sprite rendering + - Cleaner, unified settings window Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index f56c25535..00745d321 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -105,9 +105,6 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& connect(setAll, SIGNAL(pressed()), this, SLOT(setAll())); layout->addWidget(setAll); - QPushButton* save = new QPushButton(tr("Save")); - connect(save, SIGNAL(pressed()), this, SLOT(save())); - layout->addWidget(save); layout->setSpacing(6); m_keyOrder = QList{ diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 23c370f34..8737d92f5 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -9,10 +9,13 @@ #include "ConfigController.h" #include "Display.h" #include "GBAApp.h" +#include "GBAKeyEditor.h" +#include "InputController.h" +#include "ShortcutView.h" using namespace QGBA; -SettingsView::SettingsView(ConfigController* controller, QWidget* parent) +SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) , m_controller(controller) { @@ -94,6 +97,23 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent) updateConfig(); } }); + + GBAKeyEditor* editor = new GBAKeyEditor(inputController, InputController::KEYBOARD, QString(), this); + m_ui.tabWidget->addTab(editor, "Keyboard"); + connect(m_ui.buttonBox, SIGNAL(accepted()), editor, SLOT(save())); + +#ifdef BUILD_SDL + inputController->recalibrateAxes(); + const char* profile = inputController->profileForType(SDL_BINDING_BUTTON); + editor = new GBAKeyEditor(inputController, SDL_BINDING_BUTTON, profile); + m_ui.tabWidget->addTab(editor, "Controllers"); + connect(m_ui.buttonBox, SIGNAL(accepted()), editor, SLOT(save())); +#endif + + ShortcutView* shortcutView = new ShortcutView(); + shortcutView->setController(shortcutController); + shortcutView->setInputController(inputController); + m_ui.tabWidget->addTab(shortcutView, "Shortcuts"); } void SettingsView::selectBios() { diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 2a8d1302d..3947416f3 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -13,12 +13,14 @@ namespace QGBA { class ConfigController; +class InputController; +class ShortcutController; class SettingsView : public QDialog { Q_OBJECT public: - SettingsView(ConfigController* controller, QWidget* parent = nullptr); + SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent = nullptr); signals: void biosLoaded(const QString&); @@ -33,6 +35,7 @@ private: Ui::SettingsView m_ui; ConfigController* m_controller; + InputController* m_input; void saveSetting(const char* key, const QAbstractButton*); void saveSetting(const char* key, const QComboBox*); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 2e70122bf..33ca8fa89 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -6,8 +6,8 @@ 0 0 - 707 - 420 + 417 + 457 @@ -24,11 +24,17 @@ QLayout::SetFixedSize - - + + + 0 + + + + Audio/Video + - QFormLayout::ExpandingFieldsGrow + QFormLayout::FieldsStayAtSizeHint @@ -120,6 +126,50 @@ + + + + + + true + + + 44100 + + + 2 + + + + 22050 + + + + + 32000 + + + + + 44100 + + + + + 48000 + + + + + + + + Hz + + + + + @@ -154,13 +204,6 @@ - - - - Qt::Horizontal - - - @@ -237,13 +280,6 @@ - - - - Qt::Horizontal - - - @@ -283,61 +319,30 @@ - - - - - - true - - - 44100 - - - 2 - - - - 22050 - - - - - 32000 - - - - - 44100 - - - - - 48000 - - - - - - - - Hz - - - - + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + - - - - - Qt::Vertical + + + + Running + + + + QFormLayout::FieldsStayAtSizeHint - - - - @@ -366,35 +371,31 @@ - - + + - Skip BIOS intro + Use BIOS file + + + true - - - - Qt::Horizontal - - - - - - - Enable rewind - - - - + Create rewind state: - + + + + Enable rewind + + + + @@ -415,14 +416,14 @@ - + Rewind history: - + @@ -436,57 +437,14 @@ - - - - Qt::Horizontal - - - - - + + - Allow opposing input directions + Fast forward speed - - - - Suspend screensaver - - - true - - - - - - - Idle loops - - - - - - - - Run all - - - - - Remove known - - - - - Detect and remove - - - - - + false @@ -508,14 +466,7 @@ - - - - Fast forward speed - - - - + Unbounded @@ -525,26 +476,80 @@ - - - - Qt::Horizontal + + + + Allow opposing input directions - - + + - Use BIOS file + Suspend screensaver true + + + + Idle loops + + + + + + + + Run all + + + + + Remove known + + + + + Detect and remove + + + + + + + + Skip BIOS intro + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + - - + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 5d13435e4..5d6f3a53b 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -20,7 +20,6 @@ #include "Display.h" #include "GameController.h" #include "GBAApp.h" -#include "GBAKeyEditor.h" #include "GDBController.h" #include "GDBWindow.h" #include "GIFView.h" @@ -36,7 +35,6 @@ #include "SettingsView.h" #include "ShaderSelector.h" #include "ShortcutController.h" -#include "ShortcutView.h" #include "VideoView.h" extern "C" { @@ -344,29 +342,14 @@ void Window::exportSharkport() { } } -void Window::openKeymapWindow() { - GBAKeyEditor* keyEditor = new GBAKeyEditor(&m_inputController, InputController::KEYBOARD); - openView(keyEditor); -} - void Window::openSettingsWindow() { - SettingsView* settingsWindow = new SettingsView(m_config); + SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, m_shortcutController); connect(settingsWindow, SIGNAL(biosLoaded(const QString&)), m_controller, SLOT(loadBIOS(const QString&))); connect(settingsWindow, SIGNAL(audioDriverChanged()), m_controller, SLOT(reloadAudioDriver())); connect(settingsWindow, SIGNAL(displayDriverChanged()), this, SLOT(mustRestart())); openView(settingsWindow); } -void Window::openShortcutWindow() { -#ifdef BUILD_SDL - m_inputController.recalibrateAxes(); -#endif - ShortcutView* shortcutView = new ShortcutView(); - shortcutView->setController(m_shortcutController); - shortcutView->setInputController(&m_inputController); - openView(shortcutView); -} - void Window::openOverrideWindow() { OverrideView* overrideWindow = new OverrideView(m_controller, m_config); openView(overrideWindow); @@ -407,14 +390,6 @@ void Window::openROMInfo() { openView(romInfo); } -#ifdef BUILD_SDL -void Window::openGamepadWindow() { - const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON); - GBAKeyEditor* keyEditor = new GBAKeyEditor(&m_inputController, SDL_BINDING_BUTTON, profile); - openView(keyEditor); -} -#endif - #ifdef USE_FFMPEG void Window::openVideoWindow() { if (!m_videoView) { @@ -1190,18 +1165,6 @@ void Window::setupMenu(QMenuBar* menubar) { toolsMenu->addSeparator(); addControlledAction(toolsMenu, toolsMenu->addAction(tr("Settings..."), this, SLOT(openSettingsWindow())), "settings"); - addControlledAction(toolsMenu, toolsMenu->addAction(tr("Edit shortcuts..."), this, SLOT(openShortcutWindow())), - "shortcuts"); - - QAction* keymap = new QAction(tr("Remap keyboard..."), toolsMenu); - connect(keymap, SIGNAL(triggered()), this, SLOT(openKeymapWindow())); - addControlledAction(toolsMenu, keymap, "remapKeyboard"); - -#ifdef BUILD_SDL - QAction* gamepad = new QAction(tr("Remap gamepad..."), toolsMenu); - connect(gamepad, SIGNAL(triggered()), this, SLOT(openGamepadWindow())); - addControlledAction(toolsMenu, gamepad, "remapGamepad"); -#endif toolsMenu->addSeparator(); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 32a8f459a..ab0d7e99e 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -75,10 +75,7 @@ public slots: void importSharkport(); void exportSharkport(); - void openKeymapWindow(); void openSettingsWindow(); - void openShortcutWindow(); - void openOverrideWindow(); void openSensorWindow(); void openCheatsWindow(); @@ -90,10 +87,6 @@ public slots: void openAboutScreen(); void openROMInfo(); -#ifdef BUILD_SDL - void openGamepadWindow(); -#endif - #ifdef USE_FFMPEG void openVideoWindow(); #endif From 9c5852a896f042222d6e411dd39a65b3ea58ce40 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 11 Jan 2016 01:11:58 -0800 Subject: [PATCH 03/68] Qt: Added a setting for pausing when the emulator is not in focus --- CHANGES | 1 + src/platform/qt/SettingsView.cpp | 2 ++ src/platform/qt/SettingsView.ui | 13 ++++++++++--- src/platform/qt/Window.cpp | 17 +++++++++++++++++ src/platform/qt/Window.h | 3 +++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 60cb54149..6404363a1 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,7 @@ Features: - Libretro: Customizable idle loop removal - Implemented cycle counting for sprite rendering - Cleaner, unified settings window + - Added a setting for pausing when the emulator is not in focus Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 8737d92f5..e5110f7e4 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -39,6 +39,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC loadSetting("resampleVideo", m_ui.resampleVideo); loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections); loadSetting("suspendScreensaver", m_ui.suspendScreensaver); + loadSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); double fastForwardRatio = loadSetting("fastForwardRatio").toDouble(); if (fastForwardRatio <= 0) { @@ -142,6 +143,7 @@ void SettingsView::updateConfig() { saveSetting("resampleVideo", m_ui.resampleVideo); saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections); saveSetting("suspendScreensaver", m_ui.suspendScreensaver); + saveSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); if (m_ui.fastForwardUnbounded->isChecked()) { saveSetting("fastForwardRatio", "-1"); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 33ca8fa89..1e5088096 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -7,7 +7,7 @@ 0 0 417 - 457 + 478 @@ -493,14 +493,14 @@ - + Idle loops - + @@ -547,6 +547,13 @@ + + + + Pause when inactive + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 5d6f3a53b..0bdfbeb21 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -72,6 +72,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) , m_shortcutController(new ShortcutController(this)) , m_playerId(playerId) , m_fullscreenOnStart(false) + , m_autoresume(false) { setFocusPolicy(Qt::StrongFocus); setAcceptDrops(true); @@ -140,6 +141,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) connect(this, SIGNAL(sampleRateChanged(unsigned)), m_controller, SLOT(setAudioSampleRate(unsigned))); connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float))); connect(&m_fpsTimer, SIGNAL(timeout()), this, SLOT(showFPS())); + connect(&m_focusCheck, SIGNAL(timeout()), this, SLOT(focusCheck())); connect(m_display, &Display::hideCursor, [this]() { if (static_cast(m_screenWidget->layout())->currentWidget() == m_display) { m_screenWidget->setCursor(Qt::BlankCursor); @@ -152,6 +154,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) m_log.setLevels(GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS); m_fpsTimer.setInterval(FPS_TIMER_INTERVAL); + m_focusCheck.setInterval(200); m_shortcutController->setConfigController(m_config); setupMenu(menuBar()); @@ -604,6 +607,7 @@ void Window::gameStarted(GBAThread* context) { m_hitUnimplementedBiosCall = false; m_fpsTimer.start(); + m_focusCheck.start(); } void Window::gameStopped() { @@ -618,6 +622,7 @@ void Window::gameStopped() { m_screenWidget->unsetCursor(); m_fpsTimer.stop(); + m_focusCheck.stop(); } void Window::gameCrashed(const QString& errorMessage) { @@ -1354,6 +1359,18 @@ QAction* Window::addHiddenAction(QMenu* menu, QAction* action, const QString& na return action; } +void Window::focusCheck() { + if (!m_config->getOption("pauseOnFocusLost").toInt()) { + return; + } + if (QGuiApplication::focusWindow() && m_autoresume) { + m_controller->setPaused(false); + } else if (!QGuiApplication::focusWindow() && !m_controller->isPaused()) { + m_autoresume = true; + m_controller->setPaused(true); + } +} + WindowBackground::WindowBackground(QWidget* parent) : QLabel(parent) { diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index ab0d7e99e..c13c8d941 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -123,6 +123,7 @@ private slots: void recordFrame(); void showFPS(); + void focusCheck(); private: static const int FPS_TIMER_INTERVAL = 2000; @@ -164,6 +165,8 @@ private: ShaderSelector* m_shaderView; int m_playerId; bool m_fullscreenOnStart; + QTimer m_focusCheck; + bool m_autoresume; bool m_hitUnimplementedBiosCall; From 5dc56b98e896c9e246443354d77bb91a90c16c0a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 11 Jan 2016 02:36:56 -0800 Subject: [PATCH 04/68] Qt: Fix savestate problems in BIOS boot --- src/platform/qt/GameController.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 401964cd4..17cde61eb 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -110,7 +110,7 @@ GameController::GameController(QObject* parent) context->gba->video.renderer->disableOBJ = !controller->m_videoLayers[4]; controller->m_fpsTarget = context->fpsTarget; - if (GBALoadState(context, context->dirs.state, 0, SAVESTATE_SCREENSHOT)) { + if (context->dirs.state && GBALoadState(context, context->dirs.state, 0, SAVESTATE_SCREENSHOT)) { VFile* vf = GBAGetState(context->gba, context->dirs.state, 0, true); if (vf) { vf->truncate(vf, 0); @@ -696,6 +696,10 @@ void GameController::setUseBIOS(bool use) { } void GameController::loadState(int slot) { + if (!m_threadContext.fname) { + // We're in the BIOS + return; + } if (slot > 0 && slot != m_stateSlot) { m_stateSlot = slot; m_backupSaveState.clear(); @@ -714,6 +718,10 @@ void GameController::loadState(int slot) { } void GameController::saveState(int slot) { + if (!m_threadContext.fname) { + // We're in the BIOS + return; + } if (slot > 0) { m_stateSlot = slot; } From b6f1ddc4fee136f02ad261b324d34c7f194d7b3a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 11 Jan 2016 03:15:49 -0800 Subject: [PATCH 05/68] Qt: Use a sidebar instead of a tabbed view for settings --- src/platform/qt/SettingsView.cpp | 9 ++- src/platform/qt/SettingsView.ui | 101 +++++++++++++++++++------------ 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index e5110f7e4..bc2f66183 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -100,21 +100,24 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC }); GBAKeyEditor* editor = new GBAKeyEditor(inputController, InputController::KEYBOARD, QString(), this); - m_ui.tabWidget->addTab(editor, "Keyboard"); + m_ui.stackedWidget->addWidget(editor); + m_ui.tabs->addItem("Keyboard"); connect(m_ui.buttonBox, SIGNAL(accepted()), editor, SLOT(save())); #ifdef BUILD_SDL inputController->recalibrateAxes(); const char* profile = inputController->profileForType(SDL_BINDING_BUTTON); editor = new GBAKeyEditor(inputController, SDL_BINDING_BUTTON, profile); - m_ui.tabWidget->addTab(editor, "Controllers"); + m_ui.stackedWidget->addWidget(editor); + m_ui.tabs->addItem("Controllers"); connect(m_ui.buttonBox, SIGNAL(accepted()), editor, SLOT(save())); #endif ShortcutView* shortcutView = new ShortcutView(); shortcutView->setController(shortcutController); shortcutView->setInputController(inputController); - m_ui.tabWidget->addTab(shortcutView, "Shortcuts"); + m_ui.stackedWidget->addWidget(shortcutView); + m_ui.tabs->addItem("Shortcuts"); } void SettingsView::selectBios() { diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 1e5088096..001f73b40 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -6,8 +6,8 @@ 0 0 - 417 - 478 + 565 + 459 @@ -19,19 +19,13 @@ Settings - + QLayout::SetFixedSize - - - - 0 - - - - Audio/Video - + + + QFormLayout::FieldsStayAtSizeHint @@ -181,6 +175,12 @@ + + + 128 + 0 + + 256 @@ -204,6 +204,13 @@ + + + + Qt::Horizontal + + + @@ -280,6 +287,13 @@ + + + + Qt::Horizontal + + + @@ -319,26 +333,9 @@ - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - Running - + QFormLayout::FieldsStayAtSizeHint @@ -558,7 +555,33 @@ - + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + + Audio/Video + + + + + Running + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -602,18 +625,18 @@ - useBios - toggled(bool) - skipBios - setEnabled(bool) + tabs + currentRowChanged(int) + stackedWidget + setCurrentIndex(int) - 520 - 62 + 61 + 209 - 525 - 83 + 315 + 209 From 16ba5bd05ff423ba9bc98cb7615140b01ff49bd2 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 12 Jan 2016 17:43:09 -0800 Subject: [PATCH 06/68] Debugger: Fix watchpoints --- CHANGES | 1 + src/debugger/cli-debugger.c | 2 +- src/debugger/debugger.c | 3 ++- src/debugger/debugger.h | 4 ++-- src/debugger/gdb-stub.c | 16 ++++++++++++---- src/debugger/memory-debugger.c | 30 +++++++++++++++--------------- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 6404363a1..f307e4305 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Bugfixes: - GBA: Fix Iridion II savetype - Libretro: Fix aspect ratio - Qt: Fix some potential crashes with the gamepad mapping + - Debugger: Fix watchpoints in gdb Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index c3f0c9de1..1f2b54d55 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -536,7 +536,7 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* return; } uint32_t address = dv->intValue; - ARMDebuggerSetWatchpoint(&debugger->d, address); + ARMDebuggerSetWatchpoint(&debugger->d, address, WATCHPOINT_RW); // TODO: ro/wo } static void _breakIntoDefault(int signal) { diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 14e7da62a..8d696f796 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -161,12 +161,13 @@ void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) } } -void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) { +void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) { if (!debugger->watchpoints) { ARMDebuggerInstallMemoryShim(debugger); } struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint)); watchpoint->address = address; + watchpoint->type = type; watchpoint->next = debugger->watchpoints; debugger->watchpoints = watchpoint; } diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index 5abfc4cc7..94a41d1dd 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -32,7 +32,7 @@ struct DebugBreakpoint { enum WatchpointType { WATCHPOINT_WRITE = 1, WATCHPOINT_READ = 2, - WATCHPOINT_RW = 3 + WATCHPOINT_RW = WATCHPOINT_WRITE | WATCHPOINT_READ }; struct DebugWatchpoint { @@ -101,7 +101,7 @@ void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason, struct Debu void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address); bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode); void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address); -void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address); +void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type); void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address); #endif diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index 09f021805..a207bd57e 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -40,9 +40,9 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGINT); break; case DEBUGGER_ENTER_BREAKPOINT: - snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); + snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); // TODO: Use hwbreak/swbreak if gdb supports it break; - case DEBUGGER_ENTER_WATCHPOINT: // TODO: Make watchpoints raise with address + case DEBUGGER_ENTER_WATCHPOINT: if (info) { const char* type = 0; switch (info->watchType) { @@ -56,7 +56,7 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas type = "awatch"; break; } - snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%s:%08X", SIGTRAP, type, info->address); + snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%s:%08x;", SIGTRAP, type, info->address); } else { snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); } @@ -317,9 +317,17 @@ static void _setBreakpoint(struct GDBStub* stub, const char* message) { _sendMessage(stub); break; case '2': + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_WRITE); + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); + break; case '3': + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_READ); + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); + break; case '4': - ARMDebuggerSetWatchpoint(&stub->d, address); + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_RW); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; diff --git a/src/debugger/memory-debugger.c b/src/debugger/memory-debugger.c index 69d402d64..03fa1bf7f 100644 --- a/src/debugger/memory-debugger.c +++ b/src/debugger/memory-debugger.c @@ -11,7 +11,7 @@ #include -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, int width); +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width); #define FIND_DEBUGGER(DEBUGGER, CPU) \ { \ @@ -32,18 +32,18 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } -#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ +#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ACCESS_TYPE, ...) \ static RETURN ARMDebuggerShim_ ## NAME TYPES { \ struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, address, &info, WIDTH)) { \ + if (_checkWatchpoints(debugger, address, &info, ACCESS_TYPE, WIDTH)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } -#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME) \ +#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME, ACCESS_TYPE) \ static uint32_t ARMDebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \ struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ @@ -60,28 +60,28 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st unsigned i; \ for (i = 0; i < popcount; ++i) { \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, base + 4 * i, &info, 4)) { \ + if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 4)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ } \ return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \ } -CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple) -CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple) +CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple, WATCHPOINT_READ) +CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE) CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address) -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, int width) { +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) { --width; struct DebugWatchpoint* watchpoints; for (watchpoints = debugger->watchpoints; watchpoints; watchpoints = watchpoints->next) { - if (!((watchpoints->address ^ address) & ~width)) { + if (!((watchpoints->address ^ address) & ~width) && watchpoints->type & type) { switch (width + 1) { case 1: info->oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0); From e30674d05301e40ad386fd4ed32341a8bb533d95 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 12 Jan 2016 18:07:04 -0800 Subject: [PATCH 07/68] Debugger: Convert breakpoints and watchpoints from linked-lists to vectors --- CHANGES | 1 + src/debugger/debugger.c | 74 +++++++++++++++------------------- src/debugger/debugger.h | 14 ++++--- src/debugger/memory-debugger.c | 10 +++-- 4 files changed, 48 insertions(+), 51 deletions(-) diff --git a/CHANGES b/CHANGES index f307e4305..7a5f13fbd 100644 --- a/CHANGES +++ b/CHANGES @@ -58,6 +58,7 @@ Misc: - GBA RR: Add preliminary SRAM support for VBM loading - GBA RR: Add support for resets in movies - GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING + - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors 0.3.2: (2015-12-16) Bugfixes: diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 8d696f796..cccfaf3b9 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -12,10 +12,14 @@ const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF; -static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpoint* breakpoints, uint32_t address) { - for (; breakpoints; breakpoints = breakpoints->next) { - if (breakpoints->address == address) { - return breakpoints; +DEFINE_VECTOR(DebugBreakpointList, struct DebugBreakpoint); +DEFINE_VECTOR(DebugWatchpointList, struct DebugWatchpoint); + +static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpointList* breakpoints, uint32_t address) { + size_t i; + for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) { + if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) { + return DebugBreakpointListGetPointer(breakpoints, i); } } return 0; @@ -29,7 +33,7 @@ static void _checkBreakpoints(struct ARMDebugger* debugger) { } else { instructionLength = WORD_SIZE_THUMB; } - struct DebugBreakpoint* breakpoint = _lookupBreakpoint(debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength); + struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength); if (!breakpoint) { return; } @@ -52,11 +56,11 @@ void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) { struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->cpu = cpu; debugger->state = DEBUGGER_RUNNING; - debugger->breakpoints = 0; - debugger->swBreakpoints = 0; debugger->originalMemory = cpu->memory; - debugger->watchpoints = 0; debugger->currentBreakpoint = 0; + DebugBreakpointListInit(&debugger->breakpoints, 0); + DebugBreakpointListInit(&debugger->swBreakpoints, 0); + DebugWatchpointListInit(&debugger->watchpoints, 0); if (debugger->init) { debugger->init(debugger); } @@ -65,12 +69,15 @@ void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) { void ARMDebuggerDeinit(struct ARMComponent* component) { struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->deinit(debugger); + DebugBreakpointListDeinit(&debugger->breakpoints); + DebugBreakpointListDeinit(&debugger->swBreakpoints); + DebugWatchpointListDeinit(&debugger->watchpoints); } void ARMDebuggerRun(struct ARMDebugger* debugger) { switch (debugger->state) { case DEBUGGER_RUNNING: - if (!debugger->breakpoints && !debugger->watchpoints) { + if (!DebugBreakpointListSize(&debugger->breakpoints) && !DebugWatchpointListSize(&debugger->watchpoints)) { ARMRunLoop(debugger->cpu); } else { ARMRun(debugger->cpu); @@ -105,7 +112,7 @@ void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason rea struct ARMCore* cpu = debugger->cpu; cpu->nextEvent = cpu->cycles; if (reason == DEBUGGER_ENTER_BREAKPOINT) { - struct DebugBreakpoint* breakpoint = _lookupBreakpoint(debugger->swBreakpoints, _ARMPCAddress(cpu)); + struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu)); debugger->currentBreakpoint = breakpoint; if (breakpoint && breakpoint->isSw) { info->address = breakpoint->address; @@ -122,11 +129,9 @@ void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason rea } void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) { - struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint)); + struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->breakpoints); breakpoint->address = address; - breakpoint->next = debugger->breakpoints; breakpoint->isSw = false; - debugger->breakpoints = breakpoint; } bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) { @@ -135,57 +140,44 @@ bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t add return false; } - struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint)); + struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->swBreakpoints); breakpoint->address = address; - breakpoint->next = debugger->swBreakpoints; breakpoint->isSw = true; breakpoint->sw.opcode = opcode; breakpoint->sw.mode = mode; - debugger->swBreakpoints = breakpoint; return true; } void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) { - struct DebugBreakpoint** previous = &debugger->breakpoints; - struct DebugBreakpoint* breakpoint; - struct DebugBreakpoint** next; - while ((breakpoint = *previous)) { - next = &breakpoint->next; - if (breakpoint->address == address) { - *previous = *next; - free(breakpoint); - continue; + struct DebugBreakpointList* breakpoints = &debugger->breakpoints; + size_t i; + for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) { + if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) { + DebugBreakpointListShift(breakpoints, i, 1); } - previous = next; } + } void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) { - if (!debugger->watchpoints) { + if (!DebugWatchpointListSize(&debugger->watchpoints)) { ARMDebuggerInstallMemoryShim(debugger); } - struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint)); + struct DebugWatchpoint* watchpoint = DebugWatchpointListAppend(&debugger->watchpoints); watchpoint->address = address; watchpoint->type = type; - watchpoint->next = debugger->watchpoints; - debugger->watchpoints = watchpoint; } void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) { - struct DebugWatchpoint** previous = &debugger->watchpoints; - struct DebugWatchpoint* watchpoint; - struct DebugWatchpoint** next; - while ((watchpoint = *previous)) { - next = &watchpoint->next; - if (watchpoint->address == address) { - *previous = *next; - free(watchpoint); - continue; + struct DebugWatchpointList* watchpoints = &debugger->watchpoints; + size_t i; + for (i = 0; i < DebugWatchpointListSize(watchpoints); ++i) { + if (DebugWatchpointListGetPointer(watchpoints, i)->address == address) { + DebugWatchpointListShift(watchpoints, i, 1); } - previous = next; } - if (!debugger->watchpoints) { + if (!DebugWatchpointListSize(&debugger->watchpoints)) { ARMDebuggerRemoveMemoryShim(debugger); } } diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index 94a41d1dd..b236bbfda 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -8,7 +8,8 @@ #include "util/common.h" -#include "arm.h" +#include "arm/arm.h" +#include "util/vector.h" extern const uint32_t ARM_DEBUGGER_ID; @@ -20,7 +21,6 @@ enum DebuggerState { }; struct DebugBreakpoint { - struct DebugBreakpoint* next; uint32_t address; bool isSw; struct { @@ -36,11 +36,13 @@ enum WatchpointType { }; struct DebugWatchpoint { - struct DebugWatchpoint* next; uint32_t address; enum WatchpointType type; }; +DECLARE_VECTOR(DebugBreakpointList, struct DebugBreakpoint); +DECLARE_VECTOR(DebugWatchpointList, struct DebugWatchpoint); + enum DebuggerEntryReason { DEBUGGER_ENTER_MANUAL, DEBUGGER_ENTER_ATTACHED, @@ -75,9 +77,9 @@ struct ARMDebugger { enum DebuggerState state; struct ARMCore* cpu; - struct DebugBreakpoint* breakpoints; - struct DebugBreakpoint* swBreakpoints; - struct DebugWatchpoint* watchpoints; + struct DebugBreakpointList breakpoints; + struct DebugBreakpointList swBreakpoints; + struct DebugWatchpointList watchpoints; struct ARMMemory originalMemory; struct DebugBreakpoint* currentBreakpoint; diff --git a/src/debugger/memory-debugger.c b/src/debugger/memory-debugger.c index 03fa1bf7f..287217cd8 100644 --- a/src/debugger/memory-debugger.c +++ b/src/debugger/memory-debugger.c @@ -79,9 +79,11 @@ CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), addr static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) { --width; - struct DebugWatchpoint* watchpoints; - for (watchpoints = debugger->watchpoints; watchpoints; watchpoints = watchpoints->next) { - if (!((watchpoints->address ^ address) & ~width) && watchpoints->type & type) { + struct DebugWatchpoint* watchpoint; + size_t i; + for (i = 0; i < DebugWatchpointListSize(&debugger->watchpoints); ++i) { + watchpoint = DebugWatchpointListGetPointer(&debugger->watchpoints, i); + if (!((watchpoint->address ^ address) & ~width) && watchpoint->type & type) { switch (width + 1) { case 1: info->oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0); @@ -94,7 +96,7 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st break; } info->address = address; - info->watchType = watchpoints->type; + info->watchType = watchpoint->type; return true; } } From 1fa904878b07c938d849285c5b3c604e8f456ef5 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 12 Jan 2016 21:11:50 -0800 Subject: [PATCH 08/68] ARM7: Fix decoding of some ARM ALU instructions with shifters --- CHANGES | 1 + src/arm/decoder-arm.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 7a5f13fbd..206c2256b 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ Bugfixes: - Libretro: Fix aspect ratio - Qt: Fix some potential crashes with the gamepad mapping - Debugger: Fix watchpoints in gdb + - ARM7: Fix decoding of some ARM ALU instructions with shifters Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index 9a5cb7b57..c77ce6756 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -11,9 +11,9 @@ #define ADDR_MODE_1_SHIFT(OP) \ info->op3.reg = opcode & 0x0000000F; \ + info->op3.shifterOp = ARM_SHIFT_ ## OP; \ info->operandFormat |= ARM_OPERAND_REGISTER_3; \ if (opcode & 0x00000010) { \ - info->op3.shifterOp = ARM_SHIFT_ ## OP; \ info->op3.shifterReg = (opcode >> 8) & 0xF; \ ++info->iCycles; \ info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \ @@ -101,11 +101,13 @@ info->affectsCPSR = S; \ SHIFTER; \ if (SKIPPED == 1) { \ - info->operandFormat >>= 8; \ info->op1 = info->op2; \ info->op2 = info->op3; \ + info->operandFormat >>= 8; \ } else if (SKIPPED == 2) { \ - info->operandFormat &= ~ARM_OPERAND_2; \ + info->op2 = info->op3; \ + info->operandFormat |= info->operandFormat >>= 8; \ + info->operandFormat &= ~ARM_OPERAND_3; \ } \ if (info->op1.reg == ARM_PC) { \ info->branchType = ARM_BRANCH_INDIRECT; \ From 77787a957cb409e3dd730c50468f6e83981e8e8a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 12 Jan 2016 21:24:29 -0800 Subject: [PATCH 09/68] Qt: Improve some UI element sizes --- src/platform/qt/KeyEditor.cpp | 2 +- src/platform/qt/SettingsView.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/qt/KeyEditor.cpp b/src/platform/qt/KeyEditor.cpp index 34e7cf068..52877bdc3 100644 --- a/src/platform/qt/KeyEditor.cpp +++ b/src/platform/qt/KeyEditor.cpp @@ -72,7 +72,7 @@ void KeyEditor::clearAxis() { QSize KeyEditor::sizeHint() const { QSize hint = QLineEdit::sizeHint(); - hint.setWidth(40); + hint.setWidth(50); return hint; } diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 001f73b40..e0903e73b 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -6,7 +6,7 @@ 0 0 - 565 + 661 459 @@ -565,7 +565,7 @@ - 100 + 140 16777215 From 89d53868da54cb0c058dd0b61c6267bdd6514012 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 12 Jan 2016 21:35:13 -0800 Subject: [PATCH 10/68] GBA: Fix non-PNG savestate loading --- src/gba/serialize.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gba/serialize.c b/src/gba/serialize.c index a3eefe2f8..8d756bd7f 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -461,6 +461,7 @@ struct GBASerializedState* GBAExtractState(struct VFile* vf, struct GBAExtdata* return _loadPNGState(vf, extdata); } #endif + vf->seek(vf, 0, SEEK_SET); if (vf->size(vf) < (ssize_t) sizeof(struct GBASerializedState)) { return false; } From a38beac307b7b42dbc5ad5806a92b91396bea555 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 15 Jan 2016 14:29:19 -0800 Subject: [PATCH 11/68] Qt: Customizable paths for save games, save states, screenshots and patches --- CHANGES | 1 + src/gba/context/config.c | 13 ++ src/gba/context/config.h | 5 + src/gba/context/directories.c | 31 +++ src/gba/context/directories.h | 3 + src/gba/supervisor/thread.c | 5 +- src/platform/qt/ConfigController.cpp | 4 + src/platform/qt/GBAApp.cpp | 10 + src/platform/qt/GBAApp.h | 1 + src/platform/qt/GameController.cpp | 3 + src/platform/qt/SettingsView.cpp | 73 ++++++++ src/platform/qt/SettingsView.h | 1 + src/platform/qt/SettingsView.ui | 270 ++++++++++++++++++++++++++- src/platform/qt/Window.cpp | 30 +-- src/platform/qt/Window.h | 1 + src/platform/sdl/main.c | 1 + 16 files changed, 434 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 206c2256b..dc49564ea 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Features: - Implemented cycle counting for sprite rendering - Cleaner, unified settings window - Added a setting for pausing when the emulator is not in focus + - Customizable paths for save games, save states, screenshots and patches Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline diff --git a/src/gba/context/config.c b/src/gba/context/config.c index f092cda1e..e9c68cd8d 100644 --- a/src/gba/context/config.c +++ b/src/gba/context/config.c @@ -347,6 +347,11 @@ void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) { _lookupIntValue(config, "width", &opts->width); _lookupIntValue(config, "height", &opts->height); + _lookupCharValue(config, "savegamePath", &opts->savegamePath); + _lookupCharValue(config, "savestatePath", &opts->savestatePath); + _lookupCharValue(config, "screenshotPath", &opts->screenshotPath); + _lookupCharValue(config, "patchPath", &opts->patchPath); + char* idleOptimization = 0; if (_lookupCharValue(config, "idleOptimization", &idleOptimization)) { if (strcasecmp(idleOptimization, "ignore") == 0) { @@ -409,6 +414,14 @@ struct Configuration* GBAConfigGetOverrides(struct GBAConfig* config) { void GBAConfigFreeOpts(struct GBAOptions* opts) { free(opts->bios); free(opts->shader); + free(opts->savegamePath); + free(opts->savestatePath); + free(opts->screenshotPath); + free(opts->patchPath); opts->bios = 0; opts->shader = 0; + opts->savegamePath = 0; + opts->savestatePath = 0; + opts->screenshotPath = 0; + opts->patchPath = 0; } diff --git a/src/gba/context/config.h b/src/gba/context/config.h index 2ff950c7d..ce35bf614 100644 --- a/src/gba/context/config.h +++ b/src/gba/context/config.h @@ -40,6 +40,11 @@ struct GBAOptions { bool suspendScreensaver; char* shader; + char* savegamePath; + char* savestatePath; + char* screenshotPath; + char* patchPath; + int volume; bool mute; diff --git a/src/gba/context/directories.c b/src/gba/context/directories.c index d18fde029..b8bfb889f 100644 --- a/src/gba/context/directories.c +++ b/src/gba/context/directories.c @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "directories.h" +#include "gba/context/config.h" #include "util/vfs.h" void GBADirectorySetInit(struct GBADirectorySet* dirs) { @@ -99,3 +100,33 @@ struct VFile* GBADirectorySetOpenPath(struct GBADirectorySet* dirs, const char* } return file; } + +void GBADirectorySetMapOptions(struct GBADirectorySet* dirs, const struct GBAOptions* opts) { + if (opts->savegamePath) { + if (dirs->save && dirs->save != dirs->base) { + dirs->save->close(dirs->save); + } + dirs->save = VDirOpen(opts->savegamePath); + } + + if (opts->savestatePath) { + if (dirs->state && dirs->state != dirs->base) { + dirs->state->close(dirs->state); + } + dirs->state = VDirOpen(opts->savestatePath); + } + + if (opts->screenshotPath) { + if (dirs->screenshot && dirs->screenshot != dirs->base) { + dirs->screenshot->close(dirs->screenshot); + } + dirs->screenshot = VDirOpen(opts->screenshotPath); + } + + if (opts->patchPath) { + if (dirs->patch && dirs->patch != dirs->base) { + dirs->patch->close(dirs->patch); + } + dirs->patch = VDirOpen(opts->patchPath); + } +} diff --git a/src/gba/context/directories.h b/src/gba/context/directories.h index bf906c4ab..7292c59ae 100644 --- a/src/gba/context/directories.h +++ b/src/gba/context/directories.h @@ -27,4 +27,7 @@ void GBADirectorySetDetachBase(struct GBADirectorySet* dirs); struct VFile* GBADirectorySetOpenPath(struct GBADirectorySet* dirs, const char* path, bool (*filter)(struct VFile*)); +struct GBAOptions; +void GBADirectorySetMapOptions(struct GBADirectorySet* dirs, const struct GBAOptions* opts); + #endif diff --git a/src/gba/supervisor/thread.c b/src/gba/supervisor/thread.c index 8265b1775..40db25f1f 100644 --- a/src/gba/supervisor/thread.c +++ b/src/gba/supervisor/thread.c @@ -401,6 +401,8 @@ void GBAMapOptionsToContext(const struct GBAOptions* opts, struct GBAThread* thr } threadContext->idleOptimization = opts->idleOptimization; + + GBADirectorySetMapOptions(&threadContext->dirs, opts); } void GBAMapArgumentsToContext(const struct GBAArguments* args, struct GBAThread* threadContext) { @@ -441,7 +443,6 @@ bool GBAThreadStart(struct GBAThread* threadContext) { return false; } - GBADirectorySetInit(&threadContext->dirs); _reloadDirectories(threadContext); MutexInit(&threadContext->stateMutex); @@ -571,8 +572,6 @@ void GBAThreadJoin(struct GBAThread* threadContext) { threadContext->patch->close(threadContext->patch); threadContext->patch = 0; } - - GBADirectorySetDeinit(&threadContext->dirs); } bool GBAThreadIsActive(struct GBAThread* threadContext) { diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 6ab9d39d5..a2383333d 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -128,6 +128,7 @@ ConfigController::~ConfigController() { bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[], SubParser* subparser) { if (::parseArguments(args, &m_config, argc, argv, subparser)) { + GBAConfigFreeOpts(&m_opts); GBAConfigMap(&m_config, &m_opts); return true; } @@ -262,6 +263,9 @@ void ConfigController::setMRU(const QList& mru) { void ConfigController::write() { GBAConfigSave(&m_config); m_settings->sync(); + + GBAConfigFreeOpts(&m_opts); + GBAConfigMap(&m_config, &m_opts); } void ConfigController::makePortable() { diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 9fb96b303..ee35f1808 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -162,6 +162,16 @@ QString GBAApp::getSaveFileName(QWidget* owner, const QString& title, const QStr return filename; } +QString GBAApp::getOpenDirectoryName(QWidget* owner, const QString& title) { + interruptAll(); + QString filename = QFileDialog::getExistingDirectory(owner, title, m_configController.getQtOption("lastDirectory").toString()); + continueAll(); + if (!filename.isEmpty()) { + m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path()); + } + return filename; +} + QFileDialog* GBAApp::getOpenFileDialog(QWidget* owner, const QString& title, const QString& filter) { FileDialog* dialog = new FileDialog(this, owner, title, filter); dialog->setAcceptMode(QFileDialog::AcceptOpen); diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index e84f8f422..c110a51c3 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -36,6 +36,7 @@ public: QString getOpenFileName(QWidget* owner, const QString& title, const QString& filter = QString()); QString getSaveFileName(QWidget* owner, const QString& title, const QString& filter = QString()); + QString getOpenDirectoryName(QWidget* owner, const QString& title); QFileDialog* getOpenFileDialog(QWidget* owner, const QString& title, const QString& filter = QString()); QFileDialog* getSaveFileDialog(QWidget* owner, const QString& title, const QString& filter = QString()); diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 17cde61eb..65ad7528f 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -19,6 +19,7 @@ extern "C" { #include "gba/audio.h" #include "gba/context/config.h" +#include "gba/context/directories.h" #include "gba/gba.h" #include "gba/serialize.h" #include "gba/sharkport.h" @@ -216,6 +217,7 @@ GameController::~GameController() { clearMultiplayerController(); closeGame(); GBACheatDeviceDestroy(&m_cheatDevice); + GBADirectorySetDeinit(&m_threadContext.dirs); delete m_renderer; delete[] m_drawContext; delete[] m_frontBuffer; @@ -255,6 +257,7 @@ void GameController::setOptions(const GBAOptions* opts) { setMute(opts->mute); threadInterrupt(); + GBADirectorySetMapOptions(&m_threadContext.dirs, opts); m_threadContext.idleOptimization = opts->idleOptimization; threadContinue(); } diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index bc2f66183..810079459 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -40,6 +40,74 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections); loadSetting("suspendScreensaver", m_ui.suspendScreensaver); loadSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); + loadSetting("savegamePath", m_ui.savegamePath); + loadSetting("savestatePath", m_ui.savestatePath); + loadSetting("screenshotPath", m_ui.screenshotPath); + loadSetting("patchPath", m_ui.patchPath); + + if (m_ui.savegamePath->text().isEmpty()) { + m_ui.savegameSameDir->setChecked(true); + } + connect(m_ui.savegameSameDir, &QAbstractButton::toggled, [this] (bool e) { + if (e) { + m_ui.savegamePath->clear(); + } + }); + connect(m_ui.savegameBrowse, &QAbstractButton::pressed, [this] () { + QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory"); + if (!path.isNull()) { + m_ui.savegameSameDir->setChecked(false); + m_ui.savegamePath->setText(path); + } + }); + + if (m_ui.savestatePath->text().isEmpty()) { + m_ui.savestateSameDir->setChecked(true); + } + connect(m_ui.savestateSameDir, &QAbstractButton::toggled, [this] (bool e) { + if (e) { + m_ui.savestatePath->clear(); + } + }); + connect(m_ui.savestateBrowse, &QAbstractButton::pressed, [this] () { + QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory"); + if (!path.isNull()) { + m_ui.savestateSameDir->setChecked(false); + m_ui.savestatePath->setText(path); + } + }); + + if (m_ui.screenshotPath->text().isEmpty()) { + m_ui.screenshotSameDir->setChecked(true); + } + connect(m_ui.screenshotSameDir, &QAbstractButton::toggled, [this] (bool e) { + if (e) { + m_ui.screenshotPath->clear(); + } + }); + connect(m_ui.screenshotBrowse, &QAbstractButton::pressed, [this] () { + QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory"); + if (!path.isNull()) { + m_ui.screenshotSameDir->setChecked(false); + m_ui.screenshotPath->setText(path); + } + }); + + if (m_ui.patchPath->text().isEmpty()) { + m_ui.patchSameDir->setChecked(true); + } + connect(m_ui.patchSameDir, &QAbstractButton::toggled, [this] (bool e) { + if (e) { + m_ui.patchPath->clear(); + } + }); + connect(m_ui.patchBrowse, &QAbstractButton::pressed, [this] () { + QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory"); + if (!path.isNull()) { + m_ui.patchSameDir->setChecked(false); + m_ui.patchPath->setText(path); + } + }); double fastForwardRatio = loadSetting("fastForwardRatio").toDouble(); if (fastForwardRatio <= 0) { @@ -147,6 +215,10 @@ void SettingsView::updateConfig() { saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections); saveSetting("suspendScreensaver", m_ui.suspendScreensaver); saveSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); + saveSetting("savegamePath", m_ui.savegamePath); + saveSetting("savestatePath", m_ui.savestatePath); + saveSetting("screenshotPath", m_ui.screenshotPath); + saveSetting("patchPath", m_ui.patchPath); if (m_ui.fastForwardUnbounded->isChecked()) { saveSetting("fastForwardRatio", "-1"); @@ -182,6 +254,7 @@ void SettingsView::updateConfig() { m_controller->write(); + emit pathsChanged(); emit biosLoaded(m_ui.bios->text()); } diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 3947416f3..4ccdabf0e 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -26,6 +26,7 @@ signals: void biosLoaded(const QString&); void audioDriverChanged(); void displayDriverChanged(); + void pathsChanged(); private slots: void selectBios(); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index e0903e73b..6a2cca0bb 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -6,8 +6,8 @@ 0 0 - 661 - 459 + 568 + 451 @@ -25,6 +25,9 @@ + + 0 + @@ -553,6 +556,198 @@ + + + + QFormLayout::FieldsStayAtSizeHint + + + + + Save games + + + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Browse + + + + + + + + + Same directory as the ROM + + + + + + + Qt::Horizontal + + + + + + + Save states + + + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Browse + + + + + + + + + Same directory as the ROM + + + + + + + Qt::Horizontal + + + + + + + Screenshots + + + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Browse + + + + + + + + + Same directory as the ROM + + + + + + + Qt::Horizontal + + + + + + + Patches + + + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Browse + + + + + + + + + Same directory as the ROM + + + + + @@ -576,7 +771,12 @@ - Running + Emulation + + + + + Paths @@ -640,5 +840,69 @@ + + savegameSameDir + toggled(bool) + savegamePath + setDisabled(bool) + + + 392 + 82 + + + 366 + 48 + + + + + savestateSameDir + toggled(bool) + savestatePath + setDisabled(bool) + + + 392 + 161 + + + 366 + 127 + + + + + screenshotSameDir + toggled(bool) + screenshotPath + setDisabled(bool) + + + 392 + 240 + + + 366 + 206 + + + + + patchSameDir + toggled(bool) + patchPath + setDisabled(bool) + + + 345 + 319 + + + 340 + 285 + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 0bdfbeb21..e27609a62 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -198,16 +198,7 @@ void Window::setConfig(ConfigController* config) { void Window::loadConfig() { const GBAOptions* opts = m_config->options(); - - m_log.setLevels(opts->logLevel); - - m_controller->setOptions(opts); - m_display->lockAspectRatio(opts->lockAspectRatio); - m_display->filter(opts->resampleVideo); - - if (opts->bios) { - m_controller->loadBIOS(opts->bios); - } + reloadConfig(); // TODO: Move these to ConfigController if (opts->fpsTarget) { @@ -239,14 +230,28 @@ void Window::loadConfig() { } } - m_inputController.setScreensaverSuspendable(opts->suspendScreensaver); - m_mruFiles = m_config->getMRU(); updateMRU(); m_inputController.setConfiguration(m_config); } +void Window::reloadConfig() { + const GBAOptions* opts = m_config->options(); + + m_log.setLevels(opts->logLevel); + + m_controller->setOptions(opts); + m_display->lockAspectRatio(opts->lockAspectRatio); + m_display->filter(opts->resampleVideo); + + if (opts->bios) { + m_controller->loadBIOS(opts->bios); + } + + m_inputController.setScreensaverSuspendable(opts->suspendScreensaver); +} + void Window::saveConfig() { m_inputController.saveConfiguration(); m_config->write(); @@ -350,6 +355,7 @@ void Window::openSettingsWindow() { connect(settingsWindow, SIGNAL(biosLoaded(const QString&)), m_controller, SLOT(loadBIOS(const QString&))); connect(settingsWindow, SIGNAL(audioDriverChanged()), m_controller, SLOT(reloadAudioDriver())); connect(settingsWindow, SIGNAL(displayDriverChanged()), this, SLOT(mustRestart())); + connect(settingsWindow, SIGNAL(pathsChanged()), this, SLOT(reloadConfig())); openView(settingsWindow); } diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index c13c8d941..4dc927da6 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -66,6 +66,7 @@ public slots: void exitFullScreen(); void toggleFullScreen(); void loadConfig(); + void reloadConfig(); void saveConfig(); void replaceROM(); diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index d1c883707..ffc801413 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -164,6 +164,7 @@ int main(int argc, char** argv) { GBAConfigFreeOpts(&opts); GBAConfigDeinit(&config); free(context.debugger); + GBADirectorySetDeinit(&context.dirs); GBASDLDetachPlayer(&renderer.events, &renderer.player); GBAInputMapDeinit(&inputMap); From c83e4e7e851fcd268296c01eb09f21209486c69a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 15 Jan 2016 16:52:28 -0800 Subject: [PATCH 12/68] Qt: Added button for breaking into the GDB debugger --- CHANGES | 1 + src/platform/qt/GDBController.cpp | 9 +++++++++ src/platform/qt/GDBController.h | 1 + src/platform/qt/GDBWindow.cpp | 15 ++++++++++++++- src/platform/qt/GDBWindow.h | 1 + 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index dc49564ea..1f0f5aaf2 100644 --- a/CHANGES +++ b/CHANGES @@ -61,6 +61,7 @@ Misc: - GBA RR: Add support for resets in movies - GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors + - Qt: Added button for breaking into the GDB debugger 0.3.2: (2015-12-16) Bugfixes: diff --git a/src/platform/qt/GDBController.cpp b/src/platform/qt/GDBController.cpp index 197b7928d..8145fca4c 100644 --- a/src/platform/qt/GDBController.cpp +++ b/src/platform/qt/GDBController.cpp @@ -75,3 +75,12 @@ void GDBController::listen() { } m_gameController->threadContinue(); } + +void GDBController::breakInto() { + if (!isAttached()) { + return; + } + m_gameController->threadInterrupt(); + ARMDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_MANUAL, 0); + m_gameController->threadContinue(); +} diff --git a/src/platform/qt/GDBController.h b/src/platform/qt/GDBController.h index dc310d6f7..cd18fb705 100644 --- a/src/platform/qt/GDBController.h +++ b/src/platform/qt/GDBController.h @@ -34,6 +34,7 @@ public slots: void attach(); void detach(); void listen(); + void breakInto(); signals: void listening(); diff --git a/src/platform/qt/GDBWindow.cpp b/src/platform/qt/GDBWindow.cpp index eeaa76ca9..98bc89801 100644 --- a/src/platform/qt/GDBWindow.cpp +++ b/src/platform/qt/GDBWindow.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "GDBController.h" @@ -45,10 +46,20 @@ GDBWindow::GDBWindow(GDBController* controller, QWidget* parent) connect(m_bindAddressEdit, SIGNAL(textChanged(const QString&)), this, SLOT(bindAddressChanged(const QString&))); settingsGrid->addWidget(m_bindAddressEdit, 1, 1, Qt::AlignLeft); + QHBoxLayout* buttons = new QHBoxLayout; + m_startStopButton = new QPushButton; - mainSegment->addWidget(m_startStopButton); + buttons->addWidget(m_startStopButton); + + m_breakButton = new QPushButton; + m_breakButton->setText(tr("Break")); + buttons->addWidget(m_breakButton); + + mainSegment->addLayout(buttons); + connect(m_gdbController, SIGNAL(listening()), this, SLOT(started())); connect(m_gdbController, SIGNAL(listenFailed()), this, SLOT(failed())); + connect(m_breakButton, SIGNAL(clicked()), controller, SLOT(breakInto())); if (m_gdbController->isAttached()) { started(); @@ -91,6 +102,7 @@ void GDBWindow::started() { m_portEdit->setEnabled(false); m_bindAddressEdit->setEnabled(false); m_startStopButton->setText(tr("Stop")); + m_breakButton->setEnabled(true); disconnect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(listen())); connect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(detach())); connect(m_startStopButton, SIGNAL(clicked()), this, SLOT(stopped())); @@ -100,6 +112,7 @@ void GDBWindow::stopped() { m_portEdit->setEnabled(true); m_bindAddressEdit->setEnabled(true); m_startStopButton->setText(tr("Start")); + m_breakButton->setEnabled(false); disconnect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(detach())); disconnect(m_startStopButton, SIGNAL(clicked()), this, SLOT(stopped())); connect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(listen())); diff --git a/src/platform/qt/GDBWindow.h b/src/platform/qt/GDBWindow.h index 9759df05b..4e91c0e90 100644 --- a/src/platform/qt/GDBWindow.h +++ b/src/platform/qt/GDBWindow.h @@ -36,6 +36,7 @@ private: QLineEdit* m_portEdit; QLineEdit* m_bindAddressEdit; QPushButton* m_startStopButton; + QPushButton* m_breakButton; }; } From 7cf067ac144ec77c45d7707bc78b289632ce1c1a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 02:08:11 -0800 Subject: [PATCH 13/68] OpenGL: Add simple desaturation filter to default shader --- src/platform/opengl/gles2.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index cf4ef8c0d..f6ce05130 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -35,12 +35,15 @@ static const char* const _fragmentShader = "varying vec2 texCoord;\n" "uniform sampler2D tex;\n" "uniform float gamma;\n" + "uniform vec3 desaturation;\n" "uniform vec3 scale;\n" "uniform vec3 bias;\n" "void main() {\n" " vec4 color = texture2D(tex, texCoord);\n" " color.a = 1.;\n" + " float average = dot(color.rgb, vec3(1.)) / 3.;\n" + " color.rgb = vec3(average) * desaturation + color.rgb * (vec3(1.) - desaturation);\n" " color.rgb = scale * pow(color.rgb, vec3(gamma, gamma, gamma)) + bias;\n" " gl_FragColor = color;\n" "}"; @@ -82,7 +85,7 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) { glClearColor(0.f, 0.f, 0.f, 1.f); - struct GBAGLES2Uniform* uniforms = malloc(sizeof(struct GBAGLES2Uniform) * 3); + struct GBAGLES2Uniform* uniforms = malloc(sizeof(struct GBAGLES2Uniform) * 4); uniforms[0].name = "gamma"; uniforms[0].readableName = "Gamma"; uniforms[0].type = GL_FLOAT; @@ -113,7 +116,19 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) { uniforms[2].max.fvec3[0] = 1.0f; uniforms[2].max.fvec3[1] = 1.0f; uniforms[2].max.fvec3[2] = 1.0f; - GBAGLES2ShaderInit(&context->initialShader, _vertexShader, _fragmentShader, -1, -1, uniforms, 3); + uniforms[3].name = "desaturation"; + uniforms[3].readableName = "Desaturation"; + uniforms[3].type = GL_FLOAT_VEC3; + uniforms[3].value.fvec3[0] = 0.0f; + uniforms[3].value.fvec3[1] = 0.0f; + uniforms[3].value.fvec3[2] = 0.0f; + uniforms[3].min.fvec3[0] = 0.0f; + uniforms[3].min.fvec3[1] = 0.0f; + uniforms[3].min.fvec3[2] = 0.0f; + uniforms[3].max.fvec3[0] = 1.0f; + uniforms[3].max.fvec3[1] = 1.0f; + uniforms[3].max.fvec3[2] = 1.0f; + GBAGLES2ShaderInit(&context->initialShader, _vertexShader, _fragmentShader, -1, -1, uniforms, 4); GBAGLES2ShaderInit(&context->finalShader, 0, 0, 0, 0, 0, 0); glDeleteFramebuffers(1, &context->finalShader.fbo); context->finalShader.fbo = 0; From c62ff005801074e15e505a431a4f97c13d5345ac Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 02:29:03 -0800 Subject: [PATCH 14/68] OpenGL: Make all buffers expected to be the right width --- src/platform/opengl/gl.c | 6 +++--- src/platform/opengl/gles2.c | 1 - src/platform/qt/DisplayGL.cpp | 2 +- src/platform/qt/DisplayQt.cpp | 6 +++--- src/platform/qt/GameController.cpp | 8 ++++---- src/platform/sdl/gl-sdl.c | 4 ++-- src/platform/sdl/gles2-sdl.c | 4 ++-- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/platform/opengl/gl.c b/src/platform/opengl/gl.c index 5d31b89ae..7ca41e577 100644 --- a/src/platform/opengl/gl.c +++ b/src/platform/opengl/gl.c @@ -99,12 +99,12 @@ void GBAGLContextPostFrame(struct VideoBackend* v, const void* frame) { glBindTexture(GL_TEXTURE_2D, context->tex); #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame); #else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame); #endif #else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_BYTE, frame); #endif } diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index f6ce05130..f79d98134 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -278,7 +278,6 @@ void GBAGLES2ContextDrawFrame(struct VideoBackend* v) { void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) { struct GBAGLES2Context* context = (struct GBAGLES2Context*) v; glBindTexture(GL_TEXTURE_2D, context->tex); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 256); #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame); diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 249fb8f7f..6121c174b 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -366,7 +366,7 @@ void PainterGL::enqueue(const uint32_t* backing) { } else { buffer = m_free.takeLast(); } - memcpy(buffer, backing, 256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + memcpy(buffer, backing, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); m_queue.enqueue(buffer); m_mutex.unlock(); } diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index 71e684055..39502e855 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -41,12 +41,12 @@ void DisplayQt::framePosted(const uint32_t* buffer) { } #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 - m_backing = QImage(reinterpret_cast(buffer), 256, 256, QImage::Format_RGB16); + m_backing = QImage(reinterpret_cast(buffer), VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, QImage::Format_RGB16); #else - m_backing = QImage(reinterpret_cast(buffer), 256, 256, QImage::Format_RGB555); + m_backing = QImage(reinterpret_cast(buffer), VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, QImage::Format_RGB555); #endif #else - m_backing = QImage(reinterpret_cast(buffer), 256, 256, QImage::Format_RGB32); + m_backing = QImage(reinterpret_cast(buffer), VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, QImage::Format_RGB32); #endif } diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 65ad7528f..7588db1a5 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -32,8 +32,8 @@ using namespace std; GameController::GameController(QObject* parent) : QObject(parent) - , m_drawContext(new uint32_t[256 * VIDEO_HORIZONTAL_PIXELS]) - , m_frontBuffer(new uint32_t[256 * 256]) + , m_drawContext(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS]) + , m_frontBuffer(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS]) , m_threadContext() , m_activeKeys(0) , m_inactiveKeys(0) @@ -62,7 +62,7 @@ GameController::GameController(QObject* parent) m_renderer = new GBAVideoSoftwareRenderer; GBAVideoSoftwareRendererCreate(m_renderer); m_renderer->outputBuffer = (color_t*) m_drawContext; - m_renderer->outputBufferStride = 256; + m_renderer->outputBufferStride = VIDEO_HORIZONTAL_PIXELS; GBACheatDeviceCreate(&m_cheatDevice); @@ -127,7 +127,7 @@ GameController::GameController(QObject* parent) m_threadContext.frameCallback = [](GBAThread* context) { GameController* controller = static_cast(context->userData); - memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); + memcpy(controller->m_frontBuffer, controller->m_drawContext, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { GBAThreadPauseFromThread(context); diff --git a/src/platform/sdl/gl-sdl.c b/src/platform/sdl/gl-sdl.c index bb927bfce..cd5986f96 100644 --- a/src/platform/sdl/gl-sdl.c +++ b/src/platform/sdl/gl-sdl.c @@ -30,8 +30,8 @@ void GBASDLGLCreate(struct SDLSoftwareRenderer* renderer) { bool GBASDLGLInit(struct SDLSoftwareRenderer* renderer) { GBASDLGLCommonInit(renderer); - renderer->d.outputBuffer = malloc(256 * 256 * BYTES_PER_PIXEL); - renderer->d.outputBufferStride = 256; + renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS; GBAGLContextCreate(&renderer->gl); renderer->gl.d.user = renderer; diff --git a/src/platform/sdl/gles2-sdl.c b/src/platform/sdl/gles2-sdl.c index bbdffffe0..4bcbb0f94 100644 --- a/src/platform/sdl/gles2-sdl.c +++ b/src/platform/sdl/gles2-sdl.c @@ -93,8 +93,8 @@ bool GBASDLGLES2Init(struct SDLSoftwareRenderer* renderer) { GBASDLGLCommonInit(renderer); #endif - renderer->d.outputBuffer = memalign(16, 256 * 256 * 4); - renderer->d.outputBufferStride = 256; + renderer->d.outputBuffer = memalign(16, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4); + renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS; GBAGLES2ContextCreate(&renderer->gl2); renderer->gl2.d.user = renderer; From 1dceadbbf526d76c33023f7545702bdaf93452d7 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 10:02:27 -0800 Subject: [PATCH 15/68] OpenGL: Remove lingering reference to glPixelStorei --- src/platform/opengl/gles2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index f79d98134..2ca0b000e 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -287,7 +287,6 @@ void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) { #else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame); #endif - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } void GBAGLES2ContextCreate(struct GBAGLES2Context* context) { From 7e6f9f20925afc666e964d8a599331ebbf95ced9 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 10:06:01 -0800 Subject: [PATCH 16/68] ARM7: Fix typo that invoked undefined behavior --- src/arm/decoder-arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index c77ce6756..e65f8aecd 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -106,7 +106,7 @@ info->operandFormat >>= 8; \ } else if (SKIPPED == 2) { \ info->op2 = info->op3; \ - info->operandFormat |= info->operandFormat >>= 8; \ + info->operandFormat |= info->operandFormat >> 8; \ info->operandFormat &= ~ARM_OPERAND_3; \ } \ if (info->op1.reg == ARM_PC) { \ From 3fef28db198e8d1397a9aed3238b1ebf8c7352b1 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 10:59:38 -0800 Subject: [PATCH 17/68] Qt: Fix remaining write to drawContext --- src/platform/qt/GameController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 7588db1a5..30d93dd6c 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -339,7 +339,7 @@ void GameController::openGame(bool biosOnly) { } m_inputController->recalibrateAxes(); - memset(m_drawContext, 0xF8, 1024 * VIDEO_HORIZONTAL_PIXELS); + memset(m_drawContext, 0xF8, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * 4); if (!GBAThreadStart(&m_threadContext)) { m_gameOpen = false; From db6113d970d80ea271d3414ad226d3222fd361dd Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 10:59:59 -0800 Subject: [PATCH 18/68] Qt: Fix build with libepoxy and old versions of Qt5 --- src/platform/qt/DisplayGL.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 98039418a..39fa1e308 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -10,6 +10,9 @@ #ifdef USE_EPOXY #include +#ifndef GLdouble +#define GLdouble GLdouble +#endif #endif #include From ce45f6ea3fc7c686cbf43d269bdf5f69e0bcf0f3 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 16 Jan 2016 11:16:03 -0800 Subject: [PATCH 19/68] Debugger: Further differentiate read and write watchpoints, fix gdb watch behavior --- src/debugger/cli-debugger.c | 6 +++++- src/debugger/debugger.h | 2 ++ src/debugger/gdb-stub.c | 6 ++++++ src/debugger/memory-debugger.c | 35 +++++++++++++++++++++++----------- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 1f2b54d55..1a07e1768 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -802,7 +802,11 @@ static void _reportEntry(struct ARMDebugger* debugger, enum DebuggerEntryReason break; case DEBUGGER_ENTER_WATCHPOINT: if (info) { - printf("Hit watchpoint at 0x%08X: (old value = 0x%08X)\n", info->address, info->oldValue); + if (info->accessType & WATCHPOINT_WRITE) { + printf("Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->newValue, info->oldValue); + } else { + printf("Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->oldValue); + } } else { printf("Hit watchpoint\n"); } diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index b236bbfda..7f54b4f7c 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -56,7 +56,9 @@ struct DebuggerEntryInfo { union { struct { uint32_t oldValue; + uint32_t newValue; enum WatchpointType watchType; + enum WatchpointType accessType; }; struct { diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index a207bd57e..f2d2542d1 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -47,6 +47,12 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas const char* type = 0; switch (info->watchType) { case WATCHPOINT_WRITE: + if (info->newValue == info->oldValue) { + if (stub->d.state == DEBUGGER_PAUSED) { + stub->d.state = DEBUGGER_RUNNING; + } + return; + } type = "watch"; break; case WATCHPOINT_READ: diff --git a/src/debugger/memory-debugger.c b/src/debugger/memory-debugger.c index 287217cd8..750e0be04 100644 --- a/src/debugger/memory-debugger.c +++ b/src/debugger/memory-debugger.c @@ -11,7 +11,7 @@ #include -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width); +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width); #define FIND_DEBUGGER(DEBUGGER, CPU) \ { \ @@ -32,12 +32,23 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } -#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ACCESS_TYPE, ...) \ +#define CREATE_WATCHPOINT_READ_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ static RETURN ARMDebuggerShim_ ## NAME TYPES { \ struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, address, &info, ACCESS_TYPE, WIDTH)) { \ + if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_READ, 0, WIDTH)) { \ + ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ + } \ + return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ + } + +#define CREATE_WATCHPOINT_WRITE_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ + static RETURN ARMDebuggerShim_ ## NAME TYPES { \ + struct ARMDebugger* debugger; \ + FIND_DEBUGGER(debugger, cpu); \ + struct DebuggerEntryInfo info; \ + if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_WRITE, value, WIDTH)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ @@ -60,24 +71,24 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st unsigned i; \ for (i = 0; i < popcount; ++i) { \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 4)) { \ + if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 0, 4)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ } \ return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \ } -CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) -CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_WATCHPOINT_READ_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_WATCHPOINT_READ_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_WATCHPOINT_READ_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_WATCHPOINT_WRITE_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter) +CREATE_WATCHPOINT_WRITE_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter) +CREATE_WATCHPOINT_WRITE_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter) CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple, WATCHPOINT_READ) CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE) CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address) -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) { +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width) { --width; struct DebugWatchpoint* watchpoint; size_t i; @@ -95,8 +106,10 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st info->oldValue = debugger->originalMemory.load32(debugger->cpu, address, 0); break; } + info->newValue = newValue; info->address = address; info->watchType = watchpoint->type; + info->accessType = type; return true; } } From c18b9c3a64458dc7f6c0814a4b69b87c10eaefcc Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 17 Jan 2016 01:25:26 -0800 Subject: [PATCH 20/68] Qt: Allow use of OpenGL ES 2 --- src/platform/qt/DisplayGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 6121c174b..c05ecdf1c 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -188,7 +188,7 @@ PainterGL::PainterGL(QGLWidget* parent, QGLFormat::OpenGLVersionFlags glVersion) #endif #if !defined(_WIN32) || defined(USE_EPOXY) - if (glVersion & QGLFormat::OpenGL_Version_3_0) { + if (glVersion & (QGLFormat::OpenGL_Version_3_0 | QGLFormat::OpenGL_ES_Version_2_0)) { gl2Backend = new GBAGLES2Context; GBAGLES2ContextCreate(gl2Backend); m_backend = &gl2Backend->d; From 05c3159916950b8b8280348fb2b4c02c40c00ee9 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 17 Jan 2016 14:46:45 -0800 Subject: [PATCH 21/68] OpenGL: Attempt to fix OpenGL ES 2 rendering --- src/platform/opengl/gles2.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index 2ca0b000e..7beae8000 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -13,6 +13,13 @@ #define MAX_PASSES 8 +static const GLchar* const _gles2Header = + "#version 100\n" + "precision mediump float;\n"; + +static const GLchar* const _gl3Header = + "#version 120\n"; + static const char* const _vertexShader = "attribute vec4 position;\n" "varying vec2 texCoord;\n" @@ -327,16 +334,27 @@ void GBAGLES2ShaderInit(struct GBAGLES2Shader* shader, const char* vs, const cha shader->program = glCreateProgram(); shader->vertexShader = glCreateShader(GL_VERTEX_SHADER); shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar* shaderBuffer[2]; + const GLubyte* version = glGetString(GL_VERSION); + if (strncmp((const char*) version, "OpenGL ES ", strlen("OpenGL ES "))) { + shaderBuffer[0] = _gl3Header; + } else { + shaderBuffer[0] = _gles2Header; + } if (vs) { - glShaderSource(shader->vertexShader, 1, (const GLchar**) &vs, 0); + shaderBuffer[1] = vs; } else { - glShaderSource(shader->vertexShader, 1, (const GLchar**) &_nullVertexShader, 0); + shaderBuffer[1] = _nullVertexShader; } + glShaderSource(shader->vertexShader, 2, shaderBuffer, 0); + if (fs) { - glShaderSource(shader->fragmentShader, 1, (const GLchar**) &fs, 0); + shaderBuffer[1] = fs; } else { - glShaderSource(shader->fragmentShader, 1, (const GLchar**) &_nullFragmentShader, 0); + shaderBuffer[1] = _nullFragmentShader; } + glShaderSource(shader->fragmentShader, 2, shaderBuffer, 0); + glAttachShader(shader->program, shader->vertexShader); glAttachShader(shader->program, shader->fragmentShader); char log[1024]; From 6bc609b1e02610abb0a100d73c223fecb74a8611 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 17 Jan 2016 16:29:05 -0800 Subject: [PATCH 22/68] Qt: Fix GBAKeyEditor focus issues --- src/platform/qt/GBAKeyEditor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index 00745d321..cbb74fe85 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -171,9 +171,10 @@ void GBAKeyEditor::closeEvent(QCloseEvent*) { } bool GBAKeyEditor::event(QEvent* event) { - if (event->type() == QEvent::WindowActivate) { + QEvent::Type type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::Show) { m_controller->stealFocus(this); - } else if (event->type() == QEvent::WindowDeactivate) { + } else if (type == QEvent::WindowDeactivate || type == QEvent::Hide) { m_controller->releaseFocus(this); } return QWidget::event(event); From f6590de2cea808bc62a494203c7a8f04ced8aed0 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 17 Jan 2016 22:38:39 -0800 Subject: [PATCH 23/68] Qt: Fix even more potential cases of the GBAKeyEditor dangling --- src/platform/qt/GBAKeyEditor.cpp | 4 ++++ src/platform/qt/GBAKeyEditor.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index cbb74fe85..9519e89d5 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -133,6 +133,10 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& setAll->setFocus(); } +GBAKeyEditor::~GBAKeyEditor() { + m_controller->releaseFocus(this); +} + void GBAKeyEditor::setAll() { m_currentKey = m_keyOrder.begin(); (*m_currentKey)->setFocus(); diff --git a/src/platform/qt/GBAKeyEditor.h b/src/platform/qt/GBAKeyEditor.h index 8ab83442d..c555e811f 100644 --- a/src/platform/qt/GBAKeyEditor.h +++ b/src/platform/qt/GBAKeyEditor.h @@ -28,6 +28,7 @@ Q_OBJECT public: GBAKeyEditor(InputController* controller, int type, const QString& profile = QString(), QWidget* parent = nullptr); + virtual ~GBAKeyEditor(); public slots: void setAll(); From 13dfb144e88290b0e747ac51391f0882e57ce4b2 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 17 Jan 2016 22:45:25 -0800 Subject: [PATCH 24/68] SDL: Hotplugging for joysticks. Still needs work. --- CHANGES | 1 + src/platform/qt/GBAKeyEditor.cpp | 22 +++-- src/platform/qt/GBAKeyEditor.h | 1 + src/platform/qt/InputController.cpp | 35 ++++--- src/platform/qt/InputController.h | 1 + src/platform/sdl/sdl-events.c | 142 ++++++++++++++++++---------- src/platform/sdl/sdl-events.h | 25 +++-- 7 files changed, 149 insertions(+), 78 deletions(-) diff --git a/CHANGES b/CHANGES index 1f0f5aaf2..a429fcd02 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Features: - Cleaner, unified settings window - Added a setting for pausing when the emulator is not in focus - Customizable paths for save games, save states, screenshots and patches + - Controller hotplugging Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index 9519e89d5..4594fbabd 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -15,6 +15,12 @@ #include "InputController.h" #include "KeyEditor.h" +#ifdef BUILD_SDL +extern "C" { +#include "platform/sdl/sdl-events.h" +} +#endif + using namespace QGBA; const qreal GBAKeyEditor::DPAD_CENTER_X = 0.247; @@ -51,22 +57,19 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& #ifdef BUILD_SDL if (type == SDL_BINDING_BUTTON) { + controller->updateJoysticks(); controller->recalibrateAxes(); lookupAxes(map); m_profileSelect = new QComboBox(this); m_profileSelect->addItems(controller->connectedGamepads(type)); int activeGamepad = controller->gamepad(type); + selectGamepad(activeGamepad); if (activeGamepad > 0) { m_profileSelect->setCurrentIndex(activeGamepad); } - connect(m_profileSelect, static_cast(&QComboBox::currentIndexChanged), [this] (int i) { - m_controller->setGamepad(m_type, i); - m_profile = m_profileSelect->currentText(); - m_controller->loadProfile(m_type, m_profile); - refresh(); - }); + connect(m_profileSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGamepad(int))); m_clear = new QWidget(this); QHBoxLayout* layout = new QHBoxLayout; @@ -311,6 +314,13 @@ void GBAKeyEditor::setAxisValue(int axis, int32_t value) { KeyEditor* focused = *m_currentKey; focused->setValueAxis(axis, value); } + +void GBAKeyEditor::selectGamepad(int index) { + m_controller->setGamepad(m_type, index); + m_profile = m_profileSelect->currentText(); + m_controller->loadProfile(m_type, m_profile); + refresh(); +} #endif KeyEditor* GBAKeyEditor::keyById(GBAKey key) { diff --git a/src/platform/qt/GBAKeyEditor.h b/src/platform/qt/GBAKeyEditor.h index c555e811f..6637571d2 100644 --- a/src/platform/qt/GBAKeyEditor.h +++ b/src/platform/qt/GBAKeyEditor.h @@ -46,6 +46,7 @@ private slots: void refresh(); #ifdef BUILD_SDL void setAxisValue(int axis, int32_t value); + void selectGamepad(int index); #endif private: diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index a7b99ee8a..ebadbab4a 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -46,6 +46,7 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren ++s_sdlInited; m_sdlPlayer.bindings = &m_inputMap; GBASDLInitBindings(&m_inputMap); + updateJoysticks(); #endif m_gamepadTimer = new QTimer(this); @@ -146,9 +147,9 @@ const char* InputController::profileForType(uint32_t type) { #ifdef BUILD_SDL if (type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) { #if SDL_VERSION_ATLEAST(2, 0, 0) - return SDL_JoystickName(m_sdlPlayer.joystick); + return SDL_JoystickName(m_sdlPlayer.joystick->joystick); #else - return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick)); + return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick->joystick)); #endif } #endif @@ -161,12 +162,12 @@ QStringList InputController::connectedGamepads(uint32_t type) const { #ifdef BUILD_SDL if (type == SDL_BINDING_BUTTON) { QStringList pads; - for (size_t i = 0; i < s_sdlEvents.nJoysticks; ++i) { + for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) { const char* name; #if SDL_VERSION_ATLEAST(2, 0, 0) - name = SDL_JoystickName(s_sdlEvents.joysticks[i]); + name = SDL_JoystickName(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick); #else - name = SDL_JoystickName(SDL_JoystickIndex(s_sdlEvents.joysticks[i])); + name = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick)); #endif if (name) { pads.append(QString(name)); @@ -184,7 +185,7 @@ QStringList InputController::connectedGamepads(uint32_t type) const { int InputController::gamepad(uint32_t type) const { #ifdef BUILD_SDL if (type == SDL_BINDING_BUTTON) { - return m_sdlPlayer.joystickIndex; + return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0; } #endif return 0; @@ -282,11 +283,17 @@ void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) { return GBAInputBindKey(&m_inputMap, type, key, gbaKey); } +void InputController::updateJoysticks() { +#ifdef BUILD_SDL + GBASDLUpdateJoysticks(&s_sdlEvents); +#endif +} + int InputController::pollEvents() { int activeButtons = 0; #ifdef BUILD_SDL - if (m_playerAttached) { - SDL_Joystick* joystick = m_sdlPlayer.joystick; + if (m_playerAttached && m_sdlPlayer.joystick) { + SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick; SDL_JoystickUpdate(); int numButtons = SDL_JoystickNumButtons(joystick); int i; @@ -336,8 +343,8 @@ int InputController::pollEvents() { QSet InputController::activeGamepadButtons(int type) { QSet activeButtons; #ifdef BUILD_SDL - if (m_playerAttached && type == SDL_BINDING_BUTTON) { - SDL_Joystick* joystick = m_sdlPlayer.joystick; + if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) { + SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick; SDL_JoystickUpdate(); int numButtons = SDL_JoystickNumButtons(joystick); int i; @@ -353,8 +360,8 @@ QSet InputController::activeGamepadButtons(int type) { void InputController::recalibrateAxes() { #ifdef BUILD_SDL - if (m_playerAttached) { - SDL_Joystick* joystick = m_sdlPlayer.joystick; + if (m_playerAttached && m_sdlPlayer.joystick) { + SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick; SDL_JoystickUpdate(); int numAxes = SDL_JoystickNumAxes(joystick); if (numAxes < 1) { @@ -372,8 +379,8 @@ void InputController::recalibrateAxes() { QSet> InputController::activeGamepadAxes(int type) { QSet> activeAxes; #ifdef BUILD_SDL - if (m_playerAttached && type == SDL_BINDING_BUTTON) { - SDL_Joystick* joystick = m_sdlPlayer.joystick; + if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) { + SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick; SDL_JoystickUpdate(); int numAxes = SDL_JoystickNumAxes(joystick); if (numAxes < 1) { diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index f73524bad..d44078068 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -52,6 +52,7 @@ public: const GBAInputMap* map() const { return &m_inputMap; } + void updateJoysticks(); int pollEvents(); static const int32_t AXIS_THRESHOLD = 0x3000; diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 42b14b209..8ca7a617b 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -24,6 +24,8 @@ #define GYRO_STEPS 100 #define RUMBLE_PWM 20 +DEFINE_VECTOR(SDL_JoystickList, struct SDL_JoystickCombo); + #if SDL_VERSION_ATLEAST(2, 0, 0) static void _GBASDLSetRumble(struct GBARumble* rumble, int enable); #endif @@ -52,22 +54,9 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) { SDL_JoystickEventState(SDL_ENABLE); int nJoysticks = SDL_NumJoysticks(); + SDL_JoystickListInit(&context->joysticks, nJoysticks); if (nJoysticks > 0) { - context->nJoysticks = nJoysticks; - context->joysticks = calloc(context->nJoysticks, sizeof(SDL_Joystick*)); -#if SDL_VERSION_ATLEAST(2, 0, 0) - context->haptic = calloc(context->nJoysticks, sizeof(SDL_Haptic*)); -#endif - size_t i; - for (i = 0; i < context->nJoysticks; ++i) { - context->joysticks[i] = SDL_JoystickOpen(i); -#if SDL_VERSION_ATLEAST(2, 0, 0) - context->haptic[i] = SDL_HapticOpenFromJoystick(context->joysticks[i]); -#endif - } - } else { - context->nJoysticks = 0; - context->joysticks = 0; + GBASDLUpdateJoysticks(context); } context->playersAttached = 0; @@ -75,7 +64,6 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) { size_t i; for (i = 0; i < MAX_PLAYERS; ++i) { context->preferredJoysticks[i] = 0; - context->joysticksClaimed[i] = SIZE_MAX; } #if !SDL_VERSION_ATLEAST(2, 0, 0) @@ -88,13 +76,14 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) { void GBASDLDeinitEvents(struct GBASDLEvents* context) { size_t i; - for (i = 0; i < context->nJoysticks; ++i) { + for (i = 0; i < SDL_JoystickListSize(&context->joysticks); ++i) { + struct SDL_JoystickCombo* joystick = SDL_JoystickListGetPointer(&context->joysticks, i); #if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_HapticClose(context->haptic[i]); + SDL_HapticClose(joystick->haptic); #endif - SDL_JoystickClose(context->joysticks[i]); + SDL_JoystickClose(joystick->joystick); } - + SDL_JoystickListDeinit(&context->joysticks); SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } @@ -160,7 +149,6 @@ void GBASDLInitBindings(struct GBAInputMap* inputMap) { bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) { player->joystick = 0; - player->joystickIndex = SIZE_MAX; if (events->playersAttached >= MAX_PLAYERS) { return false; @@ -187,15 +175,17 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player player->rotation.p = player; player->playerId = events->playersAttached; + events->players[player->playerId] = player; size_t firstUnclaimed = SIZE_MAX; + size_t index = SIZE_MAX; size_t i; - for (i = 0; i < events->nJoysticks; ++i) { + for (i = 0; i < SDL_JoystickListSize(&events->joysticks); ++i) { bool claimed = false; int p; for (p = 0; p < events->playersAttached; ++p) { - if (events->joysticksClaimed[p] == i) { + if (events->players[p]->joystick == SDL_JoystickListGetPointer(&events->joysticks, i)) { claimed = true; break; } @@ -210,28 +200,26 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player const char* joystickName; #if SDL_VERSION_ATLEAST(2, 0, 0) - joystickName = SDL_JoystickName(events->joysticks[i]); + joystickName = SDL_JoystickName(SDL_JoystickListGetPointer(&events->joysticks, i)->joystick); #else - joystickName = SDL_JoystickName(SDL_JoystickIndex(events->joysticks[i])); + joystickName = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&events->joysticks, i)->joystick)); #endif if (events->preferredJoysticks[player->playerId] && strcmp(events->preferredJoysticks[player->playerId], joystickName) == 0) { - player->joystickIndex = i; + index = i; break; } } - if (player->joystickIndex == SIZE_MAX && firstUnclaimed != SIZE_MAX) { - player->joystickIndex = firstUnclaimed; + if (index == SIZE_MAX && firstUnclaimed != SIZE_MAX) { + index = firstUnclaimed; } - if (player->joystickIndex != SIZE_MAX) { - player->joystick = events->joysticks[player->joystickIndex]; - events->joysticksClaimed[player->playerId] = player->joystickIndex; + if (index != SIZE_MAX) { + player->joystick = SDL_JoystickListGetPointer(&events->joysticks, index); #if SDL_VERSION_ATLEAST(2, 0, 0) - player->haptic = events->haptic[player->joystickIndex]; - if (player->haptic) { - SDL_HapticRumbleInit(player->haptic); + if (player->joystick->haptic) { + SDL_HapticRumbleInit(player->joystick->haptic); } #endif } @@ -241,7 +229,19 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player } void GBASDLDetachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) { - events->joysticksClaimed[player->playerId] = SIZE_MAX; + if (player != events->players[player->playerId]) { + return; + } + int i; + for (i = player->playerId; i < events->playersAttached; ++i) { + if (i + 1 < MAX_PLAYERS) { + events->players[i] = events->players[i + 1]; + } + if (i < events->playersAttached - 1) { + events->players[i]->playerId = i; + } + } + --events->playersAttached; CircleBufferDeinit(&player->rotation.zHistory); } @@ -250,15 +250,15 @@ void GBASDLPlayerLoadConfig(struct GBASDLPlayer* context, const struct Configura if (context->joystick) { GBAInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config); #if SDL_VERSION_ATLEAST(2, 0, 0) - const char* name = SDL_JoystickName(context->joystick); + const char* name = SDL_JoystickName(context->joystick->joystick); #else - const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick)); + const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick)); #endif GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name); const char* value; char* end; - int numAxes = SDL_JoystickNumAxes(context->joystick); + int numAxes = SDL_JoystickNumAxes(context->joystick->joystick); int axis; value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisX", name); if (value) { @@ -301,9 +301,9 @@ void GBASDLPlayerLoadConfig(struct GBASDLPlayer* context, const struct Configura void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configuration* config) { if (context->joystick) { #if SDL_VERSION_ATLEAST(2, 0, 0) - const char* name = SDL_JoystickName(context->joystick); + const char* name = SDL_JoystickName(context->joystick->joystick); #else - const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick)); + const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick)); #endif char value[12]; snprintf(value, sizeof(value), "%i", context->rotation.axisX); @@ -320,14 +320,54 @@ void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configura } void GBASDLPlayerChangeJoystick(struct GBASDLEvents* events, struct GBASDLPlayer* player, size_t index) { - if (player->playerId >= MAX_PLAYERS || index >= events->nJoysticks) { + if (player->playerId >= MAX_PLAYERS || index >= SDL_JoystickListSize(&events->joysticks)) { return; } - events->joysticksClaimed[player->playerId] = index; - player->joystickIndex = index; - player->joystick = events->joysticks[index]; + player->joystick = SDL_JoystickListGetPointer(&events->joysticks, index); +} + +void GBASDLUpdateJoysticks(struct GBASDLEvents* events) { + // Pump SDL joystick events without eating the rest of the events + SDL_JoystickUpdate(); #if SDL_VERSION_ATLEAST(2, 0, 0) - player->haptic = events->haptic[index]; + SDL_Event event; + while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) { + if (event.type == SDL_JOYDEVICEADDED) { + struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks); + joystick->joystick = SDL_JoystickOpen(event.jdevice.which); + joystick->id = SDL_JoystickInstanceID(joystick->joystick); + joystick->index = SDL_JoystickListSize(&events->joysticks) - 1; +#if SDL_VERSION_ATLEAST(2, 0, 0) + joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick); +#endif + } else if (event.type == SDL_JOYDEVICEREMOVED) { + SDL_JoystickID ids[MAX_PLAYERS]; + size_t i; + for (i = 0; (int) i < events->playersAttached; ++i) { + if (events->players[i]->joystick) { + ids[i] = events->players[i]->joystick->id; + events->players[i]->joystick = 0; + } else { + ids[i] = -1; + } + } + for (i = 0; i < SDL_JoystickListSize(&events->joysticks);) { + struct SDL_JoystickCombo* joystick = SDL_JoystickListGetPointer(&events->joysticks, i); + if (joystick->id == event.jdevice.which) { + SDL_JoystickListShift(&events->joysticks, i, 1); + continue; + } + SDL_JoystickListGetPointer(&events->joysticks, i)->index = i; + int p; + for (p = 0; p < events->playersAttached; ++p) { + if (joystick->id == ids[p]) { + events->players[p]->joystick = SDL_JoystickListGetPointer(&events->joysticks, i); + } + } + ++i; + } + } + } #endif } @@ -540,7 +580,7 @@ void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContex #if SDL_VERSION_ATLEAST(2, 0, 0) static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) { struct GBASDLRumble* sdlRumble = (struct GBASDLRumble*) rumble; - if (!sdlRumble->p->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->haptic)) { + if (!sdlRumble->p->joystick->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->joystick->haptic)) { return; } sdlRumble->level += enable; @@ -551,15 +591,15 @@ static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) { } CircleBufferWrite8(&sdlRumble->history, enable); if (sdlRumble->level) { - SDL_HapticRumblePlay(sdlRumble->p->haptic, sdlRumble->level / (float) RUMBLE_PWM, 20); + SDL_HapticRumblePlay(sdlRumble->p->joystick->haptic, sdlRumble->level / (float) RUMBLE_PWM, 20); } else { - SDL_HapticRumbleStop(sdlRumble->p->haptic); + SDL_HapticRumbleStop(sdlRumble->p->joystick->haptic); } } #endif static int32_t _readTilt(struct GBASDLPlayer* player, int axis) { - return SDL_JoystickGetAxis(player->joystick, axis) * 0x3800; + return SDL_JoystickGetAxis(player->joystick->joystick, axis) * 0x3800; } static int32_t _GBASDLReadTiltX(struct GBARotationSource* source) { @@ -582,8 +622,8 @@ static void _GBASDLRotationSample(struct GBARotationSource* source) { struct GBASDLRotation* rotation = (struct GBASDLRotation*) source; SDL_JoystickUpdate(); - int x = SDL_JoystickGetAxis(rotation->p->joystick, rotation->gyroX); - int y = SDL_JoystickGetAxis(rotation->p->joystick, rotation->gyroY); + int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX); + int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY); union { float f; int32_t i; diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h index eceb9c532..015868f2e 100644 --- a/src/platform/sdl/sdl-events.h +++ b/src/platform/sdl/sdl-events.h @@ -8,6 +8,7 @@ #include "util/common.h" #include "util/circle-buffer.h" +#include "util/vector.h" #include "gba/supervisor/thread.h" @@ -21,14 +22,25 @@ struct GBAVideoSoftwareRenderer; struct Configuration; +struct SDL_JoystickCombo { + SDL_JoystickID id; + size_t index; + SDL_Joystick* joystick; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_Haptic* haptic; +#endif +}; + +DECLARE_VECTOR(SDL_JoystickList, struct SDL_JoystickCombo); + +struct GBASDLPlayer; + struct GBASDLEvents { - SDL_Joystick** joysticks; - size_t nJoysticks; + struct SDL_JoystickList joysticks; const char* preferredJoysticks[MAX_PLAYERS]; int playersAttached; - size_t joysticksClaimed[MAX_PLAYERS]; + struct GBASDLPlayer* players[MAX_PLAYERS]; #if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_Haptic** haptic; int screensaverSuspendDepth; bool screensaverSuspendable; #endif @@ -37,13 +49,11 @@ struct GBASDLEvents { struct GBASDLPlayer { size_t playerId; struct GBAInputMap* bindings; - SDL_Joystick* joystick; - size_t joystickIndex; + struct SDL_JoystickCombo* joystick; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Window* window; int fullscreen; int windowUpdated; - SDL_Haptic* haptic; struct GBASDLRumble { struct GBARumble d; @@ -80,6 +90,7 @@ bool GBASDLAttachPlayer(struct GBASDLEvents*, struct GBASDLPlayer*); void GBASDLDetachPlayer(struct GBASDLEvents*, struct GBASDLPlayer*); void GBASDLEventsLoadConfig(struct GBASDLEvents*, const struct Configuration*); void GBASDLPlayerChangeJoystick(struct GBASDLEvents*, struct GBASDLPlayer*, size_t index); +void GBASDLUpdateJoysticks(struct GBASDLEvents* events); void GBASDLInitBindings(struct GBAInputMap* inputMap); void GBASDLPlayerLoadConfig(struct GBASDLPlayer*, const struct Configuration*); From 17d343656f2bd4e0ae212d3abdc10e6e5108049a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 18 Jan 2016 19:36:13 -0800 Subject: [PATCH 25/68] Qt: Fix some focus crashes --- src/platform/qt/SensorView.cpp | 5 +++-- src/platform/qt/ShortcutView.cpp | 9 +++++++-- src/platform/qt/ShortcutView.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/SensorView.cpp b/src/platform/qt/SensorView.cpp index bf270e348..f6341e74c 100644 --- a/src/platform/qt/SensorView.cpp +++ b/src/platform/qt/SensorView.cpp @@ -81,9 +81,10 @@ void SensorView::jiggerer(QAbstractButton* button, void (InputController::*sette } bool SensorView::event(QEvent* event) { - if (event->type() == QEvent::WindowActivate) { + QEvent::Type type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::Show) { m_input->stealFocus(this); - } else if (event->type() == QEvent::WindowDeactivate) { + } else if (type == QEvent::WindowDeactivate || type == QEvent::Hide) { m_input->releaseFocus(this); } return QWidget::event(event); diff --git a/src/platform/qt/ShortcutView.cpp b/src/platform/qt/ShortcutView.cpp index 00d4385a6..9046f043c 100644 --- a/src/platform/qt/ShortcutView.cpp +++ b/src/platform/qt/ShortcutView.cpp @@ -37,6 +37,10 @@ ShortcutView::ShortcutView(QWidget* parent) connect(m_ui.clearButton, SIGNAL(clicked()), this, SLOT(clear())); } +ShortcutView::~ShortcutView() { + m_input->releaseFocus(this); +} + void ShortcutView::setController(ShortcutController* controller) { m_controller = controller; m_ui.shortcutTable->setModel(controller); @@ -117,9 +121,10 @@ void ShortcutView::closeEvent(QCloseEvent*) { bool ShortcutView::event(QEvent* event) { if (m_input) { - if (event->type() == QEvent::WindowActivate) { + QEvent::Type type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::Show) { m_input->stealFocus(this); - } else if (event->type() == QEvent::WindowDeactivate) { + } else if (type == QEvent::WindowDeactivate || type == QEvent::Hide) { m_input->releaseFocus(this); } } diff --git a/src/platform/qt/ShortcutView.h b/src/platform/qt/ShortcutView.h index 37c95c887..945f21d81 100644 --- a/src/platform/qt/ShortcutView.h +++ b/src/platform/qt/ShortcutView.h @@ -22,6 +22,7 @@ Q_OBJECT public: ShortcutView(QWidget* parent = nullptr); + ~ShortcutView(); void setController(ShortcutController* controller); void setInputController(InputController* input); From 44d1dd7f8438ce41f9d85b0e5baf09f7b2423968 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 18 Jan 2016 20:01:40 -0800 Subject: [PATCH 26/68] GBA Context: Fix reloading directories --- src/gba/context/directories.c | 36 ++++++++++++++++++++---------- src/platform/qt/GameController.cpp | 1 + 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/gba/context/directories.c b/src/gba/context/directories.c index b8bfb889f..23648567c 100644 --- a/src/gba/context/directories.c +++ b/src/gba/context/directories.c @@ -103,30 +103,42 @@ struct VFile* GBADirectorySetOpenPath(struct GBADirectorySet* dirs, const char* void GBADirectorySetMapOptions(struct GBADirectorySet* dirs, const struct GBAOptions* opts) { if (opts->savegamePath) { - if (dirs->save && dirs->save != dirs->base) { - dirs->save->close(dirs->save); + struct VDir* dir = VDirOpen(opts->savegamePath); + if (dir) { + if (dirs->save && dirs->save != dirs->base) { + dirs->save->close(dirs->save); + } + dirs->save = dir; } - dirs->save = VDirOpen(opts->savegamePath); } if (opts->savestatePath) { - if (dirs->state && dirs->state != dirs->base) { - dirs->state->close(dirs->state); + struct VDir* dir = VDirOpen(opts->savestatePath); + if (dir) { + if (dirs->state && dirs->state != dirs->base) { + dirs->state->close(dirs->state); + } + dirs->state = dir; } - dirs->state = VDirOpen(opts->savestatePath); } if (opts->screenshotPath) { - if (dirs->screenshot && dirs->screenshot != dirs->base) { - dirs->screenshot->close(dirs->screenshot); + struct VDir* dir = VDirOpen(opts->screenshotPath); + if (dir) { + if (dirs->screenshot && dirs->screenshot != dirs->base) { + dirs->screenshot->close(dirs->screenshot); + } + dirs->screenshot = dir; } - dirs->screenshot = VDirOpen(opts->screenshotPath); } if (opts->patchPath) { - if (dirs->patch && dirs->patch != dirs->base) { - dirs->patch->close(dirs->patch); + struct VDir* dir = VDirOpen(opts->patchPath); + if (dir) { + if (dirs->patch && dirs->patch != dirs->base) { + dirs->patch->close(dirs->patch); + } + dirs->patch = dir; } - dirs->patch = VDirOpen(opts->patchPath); } } diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 30d93dd6c..852bd3ffa 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -75,6 +75,7 @@ GameController::GameController(QObject* parent) m_threadContext.rewindBufferCapacity = 0; m_threadContext.cheats = &m_cheatDevice; m_threadContext.logLevel = GBA_LOG_ALL; + GBADirectorySetInit(&m_threadContext.dirs); m_lux.p = this; m_lux.sample = [](GBALuminanceSource* context) { From 0a9104113c077ad54a2a746ccb61f2c31e3db72e Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 18 Jan 2016 20:05:25 -0800 Subject: [PATCH 27/68] Qt: Fix window background --- src/platform/qt/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index e27609a62..3b11f1f12 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -104,7 +104,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) connect(m_controller, SIGNAL(rewound(GBAThread*)), m_display, SLOT(forceDraw())); connect(m_controller, &GameController::gamePaused, [this]() { QImage currentImage(reinterpret_cast(m_controller->drawContext()), VIDEO_HORIZONTAL_PIXELS, - VIDEO_VERTICAL_PIXELS, 1024, QImage::Format_RGBX8888); + VIDEO_VERTICAL_PIXELS, VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL, QImage::Format_RGBX8888); QPixmap pixmap; pixmap.convertFromImage(currentImage); m_screenWidget->setPixmap(pixmap); From 6e7851f6142a9657213de4714c3de453b229e8d7 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Wed, 20 Jan 2016 21:22:04 -0800 Subject: [PATCH 28/68] Qt: Attempt to reduce logging overhead --- src/platform/qt/LogView.cpp | 11 +++++------ src/platform/qt/LogView.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/platform/qt/LogView.cpp b/src/platform/qt/LogView.cpp index cc34ea1ca..3abead151 100644 --- a/src/platform/qt/LogView.cpp +++ b/src/platform/qt/LogView.cpp @@ -70,15 +70,13 @@ LogView::LogView(LogController* log, QWidget* parent) void LogView::postLog(int level, const QString& log) { QString line = QString("%1:\t%2").arg(LogController::toString(level)).arg(log); - if (isVisible()) { - m_ui.view->appendPlainText(line); - } else { - m_pendingLines.enqueue(line); - } + // TODO: Log to file + m_pendingLines.enqueue(line); ++m_lines; if (m_lines > m_lineLimit) { clearLine(); } + update(); } void LogView::clear() { @@ -145,10 +143,11 @@ void LogView::setMaxLines(int limit) { } } -void LogView::showEvent(QShowEvent*) { +void LogView::paintEvent(QPaintEvent* event) { while (!m_pendingLines.isEmpty()) { m_ui.view->appendPlainText(m_pendingLines.dequeue()); } + QWidget::paintEvent(event); } void LogView::clearLine() { diff --git a/src/platform/qt/LogView.h b/src/platform/qt/LogView.h index 2a84168c8..afc89af01 100644 --- a/src/platform/qt/LogView.h +++ b/src/platform/qt/LogView.h @@ -38,7 +38,7 @@ private slots: void setMaxLines(int); protected: - virtual void showEvent(QShowEvent*) override; + virtual void paintEvent(QPaintEvent*) override; private: static const int DEFAULT_LINE_LIMIT = 1000; From 60b4a490e2de76cc43caaba7226087ccc75db202 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 22 Jan 2016 21:00:08 -0800 Subject: [PATCH 29/68] Qt: Pause instead of interrupting when opening a file dialog, as the file dialog can spin the event loop --- src/platform/qt/GBAApp.cpp | 36 +++++++++++++++++++----------------- src/platform/qt/GBAApp.h | 7 +++---- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index ee35f1808..7e6da3bdf 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -124,28 +124,27 @@ GBAApp* GBAApp::app() { return g_app; } -void GBAApp::interruptAll() { +void GBAApp::pauseAll(QList* paused) { for (int i = 0; i < MAX_GBAS; ++i) { - if (!m_windows[i] || !m_windows[i]->controller()->isLoaded()) { + if (!m_windows[i] || !m_windows[i]->controller()->isLoaded() || m_windows[i]->controller()->isPaused()) { continue; } - m_windows[i]->controller()->threadInterrupt(); + m_windows[i]->controller()->setPaused(true); + paused->append(i); } } -void GBAApp::continueAll() { - for (int i = 0; i < MAX_GBAS; ++i) { - if (!m_windows[i] || !m_windows[i]->controller()->isLoaded()) { - continue; - } - m_windows[i]->controller()->threadContinue(); +void GBAApp::continueAll(const QList* paused) { + for (int i : *paused) { + m_windows[i]->controller()->setPaused(false); } } QString GBAApp::getOpenFileName(QWidget* owner, const QString& title, const QString& filter) { - interruptAll(); + QList paused; + pauseAll(&paused); QString filename = QFileDialog::getOpenFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter); - continueAll(); + continueAll(&paused); if (!filename.isEmpty()) { m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path()); } @@ -153,9 +152,10 @@ QString GBAApp::getOpenFileName(QWidget* owner, const QString& title, const QStr } QString GBAApp::getSaveFileName(QWidget* owner, const QString& title, const QString& filter) { - interruptAll(); + QList paused; + pauseAll(&paused); QString filename = QFileDialog::getSaveFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter); - continueAll(); + continueAll(&paused); if (!filename.isEmpty()) { m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path()); } @@ -163,9 +163,10 @@ QString GBAApp::getSaveFileName(QWidget* owner, const QString& title, const QStr } QString GBAApp::getOpenDirectoryName(QWidget* owner, const QString& title) { - interruptAll(); + QList paused; + pauseAll(&paused); QString filename = QFileDialog::getExistingDirectory(owner, title, m_configController.getQtOption("lastDirectory").toString()); - continueAll(); + continueAll(&paused); if (!filename.isEmpty()) { m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path()); } @@ -220,12 +221,13 @@ GBAApp::FileDialog::FileDialog(GBAApp* app, QWidget* parent, const QString& capt } int GBAApp::FileDialog::exec() { - m_app->interruptAll(); + QList paused; + m_app->pauseAll(&paused); bool didAccept = QFileDialog::exec() == QDialog::Accepted; QStringList filenames = selectedFiles(); if (!filenames.isEmpty()) { m_app->m_configController.setQtOption("lastDirectory", QFileInfo(filenames[0]).dir().path()); } - m_app->continueAll(); + m_app->continueAll(&paused); return didAccept; } diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index c110a51c3..f30be51f4 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -44,10 +44,6 @@ public: const NoIntroDB* gameDB() const { return m_db; } bool reloadGameDB(); -public slots: - void interruptAll(); - void continueAll(); - protected: bool event(QEvent*); @@ -64,6 +60,9 @@ private: Window* newWindowInternal(); + void pauseAll(QList* paused); + void continueAll(const QList* paused); + ConfigController m_configController; Window* m_windows[MAX_GBAS]; MultiplayerController m_multiplayer; From eaa81cb35839d4405ad9e53c65b0e7959e6b00ac Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 22 Jan 2016 21:34:08 -0800 Subject: [PATCH 30/68] 3DS: Fix APT usage (fixes #210) --- src/gba/gui/gui-runner.c | 10 ++++++ src/platform/3ds/main.c | 75 ++++++++++++++++++++++++++++------------ src/util/gui/menu.c | 9 +++++ 3 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/gba/gui/gui-runner.c b/src/gba/gui/gui-runner.c index 30adecb89..7d4f7eb17 100644 --- a/src/gba/gui/gui-runner.c +++ b/src/gba/gui/gui-runner.c @@ -15,6 +15,10 @@ #include "util/png-io.h" #include "util/vfs.h" +#ifdef _3DS +#include <3ds.h> +#endif + #include #define FPS_GRANULARITY 120 @@ -237,6 +241,12 @@ void GBAGUIRun(struct GBAGUIRunner* runner, const char* path) { runner->lastFpsCheck = 1000000LL * tv.tv_sec + tv.tv_usec; while (true) { +#ifdef _3DS + running = aptMainLoop(); + if (!running) { + break; + } +#endif uint32_t guiKeys; GUIPollInput(&runner->params, &guiKeys, 0); if (guiKeys & (1 << GUI_INPUT_CANCEL)) { diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 1aed46f87..fe1b74b3c 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -54,6 +54,8 @@ static struct ctrTexture gbaOutputTexture; static int guiDrawn; static int screenCleanup; +static aptHookCookie cookie; + enum { GUI_ACTIVE = 1, GUI_THIS_FRAME = 2, @@ -70,6 +72,48 @@ enum { extern bool allocateRomBuffer(void); +static void _cleanup(void) { + if (renderer.outputBuffer) { + linearFree(renderer.outputBuffer); + } + + if (gbaOutputTexture.data) { + ctrDeinitGpu(); + vramFree(gbaOutputTexture.data); + } + + gfxExit(); + + if (hasSound) { + linearFree(audioLeft); + linearFree(audioRight); + } + + csndExit(); + ptmuExit(); +} + +static void _aptHook(APT_HookType hook, void* user) { + UNUSED(user); + switch (hook) { + case APTHOOK_ONSUSPEND: + case APTHOOK_ONSLEEP: + CSND_SetPlayState(8, 0); + CSND_SetPlayState(9, 0); + csndExecCmds(false); + break; + case APTHOOK_ONEXIT: + CSND_SetPlayState(8, 0); + CSND_SetPlayState(9, 0); + csndExecCmds(false); + _cleanup(); + exit(0); + break; + default: + break; + } +} + static void _map3DSKey(struct GBAInputMap* map, int ctrKey, enum GBAKey key) { GBAInputBindKey(map, _3DS_INPUT, __builtin_ctz(ctrKey), key); } @@ -480,6 +524,8 @@ int main() { return 1; } + aptHook(&cookie, _aptHook, 0); + ptmuInit(); hasSound = !csndInit(); @@ -492,7 +538,8 @@ int main() { if (ctrInitGpu() < 0) { gbaOutputTexture.data = 0; - goto cleanup; + _cleanup(); + return 1; } ctrTexture_Init(&gbaOutputTexture); @@ -504,7 +551,8 @@ int main() { void* outputTextureEnd = (u8*)gbaOutputTexture.data + 256 * 256 * 2; if (!gbaOutputTexture.data) { - goto cleanup; + _cleanup(); + return 1; } // Zero texture data to make sure no garbage around the border interferes with filtering @@ -523,7 +571,8 @@ int main() { struct GUIFont* font = GUIFontCreate(); if (!font) { - goto cleanup; + _cleanup(); + return 1; } struct GBAGUIRunner runner = { @@ -610,24 +659,6 @@ int main() { GBAGUIRunloop(&runner); GBAGUIDeinit(&runner); -cleanup: - if (renderer.outputBuffer) { - linearFree(renderer.outputBuffer); - } - - if (gbaOutputTexture.data) { - ctrDeinitGpu(); - vramFree(gbaOutputTexture.data); - } - - gfxExit(); - - if (hasSound) { - linearFree(audioLeft); - linearFree(audioRight); - } - - csndExit(); - ptmuExit(); + _cleanup(); return 0; } diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index b65d76052..283468542 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -8,6 +8,10 @@ #include "util/gui.h" #include "util/gui/font.h" +#ifdef _3DS +#include <3ds.h> +#endif + DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem); enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item) { @@ -23,6 +27,11 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men GUIInvalidateKeys(params); while (true) { +#ifdef _3DS + if (!aptMainLoop()) { + return GUI_MENU_EXIT_CANCEL; + } +#endif uint32_t newInput = 0; GUIPollInput(params, &newInput, 0); unsigned cx, cy; From d6bccd80f724670c4c17ebf1615f440158ea12db Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 22 Jan 2016 22:43:51 -0800 Subject: [PATCH 31/68] Util: Fix MutexTryLock on Windows --- src/platform/windows/threading.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/windows/threading.h b/src/platform/windows/threading.h index 37427bf23..efcf3a091 100644 --- a/src/platform/windows/threading.h +++ b/src/platform/windows/threading.h @@ -34,7 +34,7 @@ static inline int MutexLock(Mutex* mutex) { static inline int MutexTryLock(Mutex* mutex) { if (TryEnterCriticalSection(mutex)) { - return GetLastError(); + return 0; } return 1; } From 380f6dbe7e42dc3c67eee39cccb226c13d9b9a05 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 02:34:27 -0800 Subject: [PATCH 32/68] OpenGL: Add integer scaling forcing and a pixelate filter --- res/shaders/pixelate.shader/manifest.ini | 9 +++++++++ src/platform/opengl/gles2.c | 19 ++++++++++++++----- src/platform/opengl/gles2.h | 3 ++- 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 res/shaders/pixelate.shader/manifest.ini diff --git a/res/shaders/pixelate.shader/manifest.ini b/res/shaders/pixelate.shader/manifest.ini new file mode 100644 index 000000000..b2c55560a --- /dev/null +++ b/res/shaders/pixelate.shader/manifest.ini @@ -0,0 +1,9 @@ +[shader] +name=Pixelate +author=endrift +description=Only scale up the screen at an integer ratio +passes=1 + +[pass.0] +blend=1 +integerScaling=1 diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index 7beae8000..cff5dab27 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -135,8 +135,8 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) { uniforms[3].max.fvec3[0] = 1.0f; uniforms[3].max.fvec3[1] = 1.0f; uniforms[3].max.fvec3[2] = 1.0f; - GBAGLES2ShaderInit(&context->initialShader, _vertexShader, _fragmentShader, -1, -1, uniforms, 4); - GBAGLES2ShaderInit(&context->finalShader, 0, 0, 0, 0, 0, 0); + GBAGLES2ShaderInit(&context->initialShader, _vertexShader, _fragmentShader, -1, -1, false, uniforms, 4); + GBAGLES2ShaderInit(&context->finalShader, 0, 0, 0, 0, false, 0, 0); glDeleteFramebuffers(1, &context->finalShader.fbo); context->finalShader.fbo = 0; } @@ -195,6 +195,12 @@ void _drawShader(struct GBAGLES2Shader* shader) { drawH = viewport[3]; padH = viewport[1]; } + if (shader->integerScaling) { + padW = 0; + padH = 0; + drawW -= drawW % VIDEO_HORIZONTAL_PIXELS; + drawH -= drawH % VIDEO_VERTICAL_PIXELS; + } glViewport(padW, padH, drawW, drawH); if (!shader->width || !shader->height) { GLint oldTex; @@ -204,7 +210,7 @@ void _drawShader(struct GBAGLES2Shader* shader) { glBindTexture(GL_TEXTURE_2D, oldTex); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST); glUseProgram(shader->program); glUniform1i(shader->texLocation, 0); @@ -310,9 +316,10 @@ void GBAGLES2ContextCreate(struct GBAGLES2Context* context) { context->nShaders = 0; } -void GBAGLES2ShaderInit(struct GBAGLES2Shader* shader, const char* vs, const char* fs, int width, int height, struct GBAGLES2Uniform* uniforms, size_t nUniforms) { +void GBAGLES2ShaderInit(struct GBAGLES2Shader* shader, const char* vs, const char* fs, int width, int height, bool integerScaling, struct GBAGLES2Uniform* uniforms, size_t nUniforms) { shader->width = width >= 0 ? width : VIDEO_HORIZONTAL_PIXELS; shader->height = height >= 0 ? height : VIDEO_VERTICAL_PIXELS; + shader->integerScaling = integerScaling; shader->filter = false; shader->blend = false; shader->uniforms = uniforms; @@ -802,8 +809,10 @@ bool GBAGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { } int width = 0; int height = 0; + int scaling = 0; _lookupIntValue(&description, passName, "width", &width); _lookupIntValue(&description, passName, "height", &height); + _lookupIntValue(&description, passName, "integerScaling", &scaling); struct GBAGLES2UniformList uniformVector; GBAGLES2UniformListInit(&uniformVector, 0); @@ -821,7 +830,7 @@ bool GBAGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { memcpy(uniformBlock, GBAGLES2UniformListGetPointer(&uniformVector, 0), sizeof(*uniformBlock) * u); GBAGLES2UniformListDeinit(&uniformVector); - GBAGLES2ShaderInit(&shaderBlock[n], vssrc, fssrc, width, height, uniformBlock, u); + GBAGLES2ShaderInit(&shaderBlock[n], vssrc, fssrc, width, height, scaling, uniformBlock, u); int b = 0; _lookupIntValue(&description, passName, "blend", &b); if (b) { diff --git a/src/platform/opengl/gles2.h b/src/platform/opengl/gles2.h index cf28eb602..fa623b94f 100644 --- a/src/platform/opengl/gles2.h +++ b/src/platform/opengl/gles2.h @@ -53,6 +53,7 @@ struct GBAGLES2Uniform { struct GBAGLES2Shader { unsigned width; unsigned height; + bool integerScaling; bool filter; bool blend; GLuint tex; @@ -83,7 +84,7 @@ struct GBAGLES2Context { void GBAGLES2ContextCreate(struct GBAGLES2Context*); -void GBAGLES2ShaderInit(struct GBAGLES2Shader*, const char* vs, const char* fs, int width, int height, struct GBAGLES2Uniform* uniforms, size_t nUniforms); +void GBAGLES2ShaderInit(struct GBAGLES2Shader*, const char* vs, const char* fs, int width, int height, bool integerScaling, struct GBAGLES2Uniform* uniforms, size_t nUniforms); void GBAGLES2ShaderDeinit(struct GBAGLES2Shader*); void GBAGLES2ShaderAttach(struct GBAGLES2Context*, struct GBAGLES2Shader*, size_t nShaders); void GBAGLES2ShaderDetach(struct GBAGLES2Context*); From b5c813e829ffa88e7027ff28aa276e45d8bced62 Mon Sep 17 00:00:00 2001 From: Sergi Granell Date: Sat, 23 Jan 2016 12:27:42 +0100 Subject: [PATCH 33/68] Vita: Update to latest SDK version --- src/platform/psp2/main.c | 20 +++++++++----------- src/platform/psp2/psp2-context.c | 24 ++++++++++++------------ src/platform/psp2/sce-vfs.c | 2 +- src/util/vfs.c | 14 +++++++------- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/platform/psp2/main.c b/src/platform/psp2/main.c index 3c8fd30a3..708d9dd36 100644 --- a/src/platform/psp2/main.c +++ b/src/platform/psp2/main.c @@ -22,8 +22,6 @@ #include -PSP2_MODULE_INFO(0, 0, "mGBA"); - static void _drawStart(void) { vita2d_set_vblank_wait(false); vita2d_start_drawing(); @@ -43,29 +41,29 @@ static uint32_t _pollInput(void) { SceCtrlData pad; sceCtrlPeekBufferPositive(0, &pad, 1); int input = 0; - if (pad.buttons & PSP2_CTRL_TRIANGLE) { + if (pad.buttons & SCE_CTRL_TRIANGLE) { input |= 1 << GUI_INPUT_CANCEL; } - if (pad.buttons & PSP2_CTRL_SQUARE) { + if (pad.buttons & SCE_CTRL_SQUARE) { input |= 1 << GBA_GUI_INPUT_SCREEN_MODE; } - if (pad.buttons & PSP2_CTRL_CIRCLE) { + if (pad.buttons & SCE_CTRL_CIRCLE) { input |= 1 << GUI_INPUT_BACK; } - if (pad.buttons & PSP2_CTRL_CROSS) { + if (pad.buttons & SCE_CTRL_CROSS) { input |= 1 << GUI_INPUT_SELECT; } - if (pad.buttons & PSP2_CTRL_UP || pad.ly < 64) { + if (pad.buttons & SCE_CTRL_UP || pad.ly < 64) { input |= 1 << GUI_INPUT_UP; } - if (pad.buttons & PSP2_CTRL_DOWN || pad.ly >= 192) { + if (pad.buttons & SCE_CTRL_DOWN || pad.ly >= 192) { input |= 1 << GUI_INPUT_DOWN; } - if (pad.buttons & PSP2_CTRL_LEFT || pad.lx < 64) { + if (pad.buttons & SCE_CTRL_LEFT || pad.lx < 64) { input |= 1 << GUI_INPUT_LEFT; } - if (pad.buttons & PSP2_CTRL_RIGHT || pad.lx >= 192) { + if (pad.buttons & SCE_CTRL_RIGHT || pad.lx >= 192) { input |= 1 << GUI_INPUT_RIGHT; } @@ -108,7 +106,7 @@ int main() { GUI_PARAMS_TRAIL }, .configExtra = (struct GUIMenuItem[]) { - { + { .title = "Screen mode", .data = "screenMode", .submenu = 0, diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index 9c880b71c..3f567e209 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -65,7 +65,7 @@ static void _mapVitaKey(struct GBAInputMap* map, int pspKey, enum GBAKey key) { static THREAD_ENTRY _audioThread(void* context) { struct GBAPSP2AudioContext* audio = (struct GBAPSP2AudioContext*) context; struct GBAStereoSample buffer[PSP2_SAMPLES]; - int audioPort = sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, PSP2_AUDIO_OUT_MODE_STEREO); + int audioPort = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO); while (audio->running) { memset(buffer, 0, sizeof(buffer)); MutexLock(&audio->mutex); @@ -75,7 +75,7 @@ static THREAD_ENTRY _audioThread(void* context) { len = PSP2_SAMPLES; } if (len > 0) { - len &= ~(PSP2_AUDIO_MIN_LEN - 1); + len &= ~(SCE_AUDIO_MIN_LEN - 1); CircleBufferRead(&audio->buffer, buffer, len * sizeof(buffer[0])); MutexUnlock(&audio->mutex); sceAudioOutOutput(audioPort, buffer); @@ -137,16 +137,16 @@ uint16_t GBAPSP2PollInput(struct GBAGUIRunner* runner) { void GBAPSP2Setup(struct GBAGUIRunner* runner) { scePowerSetArmClockFrequency(80); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_CROSS, GBA_KEY_A); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_START, GBA_KEY_START); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_SELECT, GBA_KEY_SELECT); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_UP, GBA_KEY_UP); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_DOWN, GBA_KEY_DOWN); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_LEFT, GBA_KEY_LEFT); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_RIGHT, GBA_KEY_RIGHT); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_LTRIGGER, GBA_KEY_L); - _mapVitaKey(&runner->context.inputMap, PSP2_CTRL_RTRIGGER, GBA_KEY_R); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_CROSS, GBA_KEY_A); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_CIRCLE, GBA_KEY_B); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_START, GBA_KEY_START); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_SELECT, GBA_KEY_SELECT); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_UP, GBA_KEY_UP); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_DOWN, GBA_KEY_DOWN); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_LEFT, GBA_KEY_LEFT); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_RIGHT, GBA_KEY_RIGHT); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_LTRIGGER, GBA_KEY_L); + _mapVitaKey(&runner->context.inputMap, SCE_CTRL_RTRIGGER, GBA_KEY_R); struct GBAAxis desc = { GBA_KEY_DOWN, GBA_KEY_UP, 192, 64 }; GBAInputBindAxis(&runner->context.inputMap, PSP2_INPUT, 0, &desc); diff --git a/src/platform/psp2/sce-vfs.c b/src/platform/psp2/sce-vfs.c index 6b7666320..de057eb34 100644 --- a/src/platform/psp2/sce-vfs.c +++ b/src/platform/psp2/sce-vfs.c @@ -222,7 +222,7 @@ static const char* _vdesceName(struct VDirEntry* vde) { static enum VFSType _vdesceType(struct VDirEntry* vde) { struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde; - if (PSP2_S_ISDIR(vdesce->ent.d_stat.st_mode)) { + if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) { return VFS_DIRECTORY; } return VFS_FILE; diff --git a/src/util/vfs.c b/src/util/vfs.c index d6102632f..5f6533762 100644 --- a/src/util/vfs.c +++ b/src/util/vfs.c @@ -40,27 +40,27 @@ struct VFile* VFileOpen(const char* path, int flags) { } return VFileFOpen(path, chflags); #elif defined(PSP2) - int sceFlags = PSP2_O_RDONLY; + int sceFlags = SCE_O_RDONLY; switch (flags & O_ACCMODE) { case O_WRONLY: - sceFlags = PSP2_O_WRONLY; + sceFlags = SCE_O_WRONLY; break; case O_RDWR: - sceFlags = PSP2_O_RDWR; + sceFlags = SCE_O_RDWR; break; case O_RDONLY: - sceFlags = PSP2_O_RDONLY; + sceFlags = SCE_O_RDONLY; break; } if (flags & O_APPEND) { - sceFlags |= PSP2_O_APPEND; + sceFlags |= SCE_O_APPEND; } if (flags & O_TRUNC) { - sceFlags |= PSP2_O_TRUNC; + sceFlags |= SCE_O_TRUNC; } if (flags & O_CREAT) { - sceFlags |= PSP2_O_CREAT; + sceFlags |= SCE_O_CREAT; } return VFileOpenSce(path, sceFlags, 0666); #elif defined(USE_VFS_3DS) From c5f4b6ead2faba89851e8c104e9791992dfbbfbb Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 14:00:29 -0800 Subject: [PATCH 34/68] Shaders: Add xBR lv3 shader by Hyllian --- res/shaders/xbr.shader/manifest.ini | 9 + res/shaders/xbr.shader/xbr.fs | 510 ++++++++++++++++++++++++++++ res/shaders/xbr.shader/xbr.vs | 78 +++++ 3 files changed, 597 insertions(+) create mode 100644 res/shaders/xbr.shader/manifest.ini create mode 100644 res/shaders/xbr.shader/xbr.fs create mode 100644 res/shaders/xbr.shader/xbr.vs diff --git a/res/shaders/xbr.shader/manifest.ini b/res/shaders/xbr.shader/manifest.ini new file mode 100644 index 000000000..a070badbd --- /dev/null +++ b/res/shaders/xbr.shader/manifest.ini @@ -0,0 +1,9 @@ +[shader] +name=xBR +author=Hyllian +passes=1 + +[pass.0] +integerScaling=1 +vertexShader=xbr.vs +fragmentShader=xbr.fs diff --git a/res/shaders/xbr.shader/xbr.fs b/res/shaders/xbr.shader/xbr.fs new file mode 100644 index 000000000..72f726e4d --- /dev/null +++ b/res/shaders/xbr.shader/xbr.fs @@ -0,0 +1,510 @@ +/* + Hyllian's xBR-lv3 Shader + + Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + + Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. +*/ +// GLSL shader autogenerated by cg2glsl.py. +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +vec4 _ret_0; +float _TMP57; +float _TMP56; +float _TMP55; +vec3 _TMP54; +vec3 _TMP53; +vec3 _TMP52; +vec3 _TMP51; +vec3 _TMP50; +vec3 _TMP49; +vec3 _TMP48; +vec3 _TMP47; +vec4 _TMP46; +vec4 _TMP45; +vec4 _TMP44; +vec4 _TMP37; +vec4 _TMP36; +vec4 _TMP65; +bvec4 _TMP35; +bvec4 _TMP34; +bvec4 _TMP33; +bvec4 _TMP32; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D tex; +vec2 _x0078; +vec4 _r0122; +vec4 _r0132; +vec4 _r0142; +vec4 _r0152; +vec4 _r0162; +vec4 _r0172; +vec4 _TMP183; +vec4 _a0186; +vec4 _TMP189; +vec4 _a0192; +vec4 _TMP195; +vec4 _a0198; +vec4 _TMP201; +vec4 _a0204; +vec4 _TMP207; +vec4 _a0210; +vec4 _TMP213; +vec4 _a0216; +vec4 _TMP219; +vec4 _a0222; +vec4 _TMP225; +vec4 _a0228; +vec4 _TMP231; +vec4 _a0234; +vec4 _TMP237; +vec4 _a0240; +vec4 _TMP243; +vec4 _a0246; +vec4 _TMP249; +vec4 _a0252; +vec4 _TMP255; +vec4 _a0258; +vec4 _TMP261; +vec4 _a0264; +vec4 _TMP267; +vec4 _a0270; +vec4 _x0274; +vec4 _TMP275; +vec4 _x0284; +vec4 _TMP285; +vec4 _x0294; +vec4 _TMP295; +vec4 _x0304; +vec4 _TMP305; +vec4 _x0314; +vec4 _TMP315; +vec4 _TMP323; +vec4 _a0326; +vec4 _TMP327; +vec4 _a0330; +vec4 _TMP331; +vec4 _a0334; +vec4 _TMP335; +vec4 _a0338; +vec4 _TMP339; +vec4 _a0342; +vec4 _TMP345; +vec4 _a0348; +vec4 _TMP349; +vec4 _a0352; +vec4 _TMP353; +vec4 _a0356; +vec4 _TMP357; +vec4 _a0360; +vec4 _TMP361; +vec4 _a0364; +vec4 _TMP365; +vec4 _a0368; +vec4 _TMP369; +vec4 _a0372; +vec4 _TMP373; +vec4 _a0376; +vec4 _TMP377; +vec4 _a0380; +vec4 _TMP381; +vec4 _a0384; +vec4 _TMP385; +vec4 _a0388; +vec3 _df0402; +vec3 _a0404; +vec3 _df0406; +vec3 _a0408; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +const COMPAT_PRECISION vec2 TextureSize = vec2(240.0, 160.0); +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _interp_restriction_lv3_left; + bvec4 _interp_restriction_lv3_up; + bvec4 _nc; + bvec4 _nc30; + bvec4 _nc60; + bvec4 _nc45; + bvec4 _nc15; + bvec4 _nc75; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec4 _fx3_left; + vec4 _fx3_up; + vec3 _res1; + vec3 _res2; + vec3 _pix1; + vec3 _pix2; + float _blend1; + float _blend2; + vec2 _fp; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _fx15; + vec4 _fx75; + vec4 _final45; + vec4 _final30; + vec4 _final60; + vec4 _final15; + vec4 _final75; + vec4 _maximo; + vec3 _res; + _x0078 = TEX0.xy*TextureSize; + _fp = fract(_x0078); + _TMP0 = COMPAT_TEXTURE(tex, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(tex, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(tex, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(tex, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(tex, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(tex, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(tex, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(tex, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(tex, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(tex, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(tex, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(tex, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(tex, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(tex, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(tex, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(tex, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(tex, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(tex, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(tex, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(tex, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(tex, TEX7.xw); + _r0122.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _fx3_left = vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x; + _fx3_up = vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x; + _a0186 = _r0122.wxyz - _r0122; + _TMP183 = abs(_a0186); + _TMP21 = bvec4(_TMP183.x < 1.00000000E+01, _TMP183.y < 1.00000000E+01, _TMP183.z < 1.00000000E+01, _TMP183.w < 1.00000000E+01); + _a0192 = _r0122.wxyz - _r0132; + _TMP189 = abs(_a0192); + _TMP22 = bvec4(_TMP189.x < 1.00000000E+01, _TMP189.y < 1.00000000E+01, _TMP189.z < 1.00000000E+01, _TMP189.w < 1.00000000E+01); + _a0198 = _r0122.zwxy - _r0122.yzwx; + _TMP195 = abs(_a0198); + _TMP23 = bvec4(_TMP195.x < 1.00000000E+01, _TMP195.y < 1.00000000E+01, _TMP195.z < 1.00000000E+01, _TMP195.w < 1.00000000E+01); + _a0204 = _r0122.zwxy - _r0132.zwxy; + _TMP201 = abs(_a0204); + _TMP24 = bvec4(_TMP201.x < 1.00000000E+01, _TMP201.y < 1.00000000E+01, _TMP201.z < 1.00000000E+01, _TMP201.w < 1.00000000E+01); + _a0210 = _r0142 - _r0132.wxyz; + _TMP207 = abs(_a0210); + _TMP25 = bvec4(_TMP207.x < 1.00000000E+01, _TMP207.y < 1.00000000E+01, _TMP207.z < 1.00000000E+01, _TMP207.w < 1.00000000E+01); + _a0216 = _r0122.wxyz - _r0172.yzwx; + _TMP213 = abs(_a0216); + _TMP26 = bvec4(_TMP213.x < 1.00000000E+01, _TMP213.y < 1.00000000E+01, _TMP213.z < 1.00000000E+01, _TMP213.w < 1.00000000E+01); + _a0222 = _r0122.wxyz - _r0152; + _TMP219 = abs(_a0222); + _TMP27 = bvec4(_TMP219.x < 1.00000000E+01, _TMP219.y < 1.00000000E+01, _TMP219.z < 1.00000000E+01, _TMP219.w < 1.00000000E+01); + _a0228 = _r0122.zwxy - _r0172; + _TMP225 = abs(_a0228); + _TMP28 = bvec4(_TMP225.x < 1.00000000E+01, _TMP225.y < 1.00000000E+01, _TMP225.z < 1.00000000E+01, _TMP225.w < 1.00000000E+01); + _a0234 = _r0122.zwxy - _r0162; + _TMP231 = abs(_a0234); + _TMP29 = bvec4(_TMP231.x < 1.00000000E+01, _TMP231.y < 1.00000000E+01, _TMP231.z < 1.00000000E+01, _TMP231.w < 1.00000000E+01); + _a0240 = _r0142 - _r0132.zwxy; + _TMP237 = abs(_a0240); + _TMP30 = bvec4(_TMP237.x < 1.00000000E+01, _TMP237.y < 1.00000000E+01, _TMP237.z < 1.00000000E+01, _TMP237.w < 1.00000000E+01); + _a0246 = _r0142 - _r0132; + _TMP243 = abs(_a0246); + _TMP31 = bvec4(_TMP243.x < 1.00000000E+01, _TMP243.y < 1.00000000E+01, _TMP243.z < 1.00000000E+01, _TMP243.w < 1.00000000E+01); + _interp_restriction_lv1 = bvec4(_r0142.x != _r0122.w && _r0142.x != _r0122.z && (!_TMP21.x && !_TMP22.x || !_TMP23.x && !_TMP24.x || _TMP25.x && (!_TMP26.x && !_TMP27.x || !_TMP28.x && !_TMP29.x) || _TMP30.x || _TMP31.x), _r0142.y != _r0122.x && _r0142.y != _r0122.w && (!_TMP21.y && !_TMP22.y || !_TMP23.y && !_TMP24.y || _TMP25.y && (!_TMP26.y && !_TMP27.y || !_TMP28.y && !_TMP29.y) || _TMP30.y || _TMP31.y), _r0142.z != _r0122.y && _r0142.z != _r0122.x && (!_TMP21.z && !_TMP22.z || !_TMP23.z && !_TMP24.z || _TMP25.z && (!_TMP26.z && !_TMP27.z || !_TMP28.z && !_TMP29.z) || _TMP30.z || _TMP31.z), _r0142.w != _r0122.z && _r0142.w != _r0122.y && (!_TMP21.w && !_TMP22.w || !_TMP23.w && !_TMP24.w || _TMP25.w && (!_TMP26.w && !_TMP27.w || !_TMP28.w && !_TMP29.w) || _TMP30.w || _TMP31.w)); + _interp_restriction_lv2_left = bvec4(_r0142.x != _r0132.z && _r0122.y != _r0132.z, _r0142.y != _r0132.w && _r0122.z != _r0132.w, _r0142.z != _r0132.x && _r0122.w != _r0132.x, _r0142.w != _r0132.y && _r0122.x != _r0132.y); + _interp_restriction_lv2_up = bvec4(_r0142.x != _r0132.x && _r0122.x != _r0132.x, _r0142.y != _r0132.y && _r0122.y != _r0132.y, _r0142.z != _r0132.z && _r0122.z != _r0132.z, _r0142.w != _r0132.w && _r0122.w != _r0132.w); + _a0252 = _r0132.zwxy - _r0162.wxyz; + _TMP249 = abs(_a0252); + _TMP32 = bvec4(_TMP249.x < 2.00000000E+00, _TMP249.y < 2.00000000E+00, _TMP249.z < 2.00000000E+00, _TMP249.w < 2.00000000E+00); + _a0258 = _r0172.wxyz - _r0162.wxyz; + _TMP255 = abs(_a0258); + _TMP33 = bvec4(_TMP255.x < 2.00000000E+00, _TMP255.y < 2.00000000E+00, _TMP255.z < 2.00000000E+00, _TMP255.w < 2.00000000E+00); + _interp_restriction_lv3_left = bvec4(_TMP32.x && !_TMP33.x, _TMP32.y && !_TMP33.y, _TMP32.z && !_TMP33.z, _TMP32.w && !_TMP33.w); + _a0264 = _r0132 - _r0152.yzwx; + _TMP261 = abs(_a0264); + _TMP34 = bvec4(_TMP261.x < 2.00000000E+00, _TMP261.y < 2.00000000E+00, _TMP261.z < 2.00000000E+00, _TMP261.w < 2.00000000E+00); + _a0270 = _r0172.zwxy - _r0152.yzwx; + _TMP267 = abs(_a0270); + _TMP35 = bvec4(_TMP267.x < 2.00000000E+00, _TMP267.y < 2.00000000E+00, _TMP267.z < 2.00000000E+00, _TMP267.w < 2.00000000E+00); + _interp_restriction_lv3_up = bvec4(_TMP34.x && !_TMP35.x, _TMP34.y && !_TMP35.y, _TMP34.z && !_TMP35.z, _TMP34.w && !_TMP35.w); + _x0274 = (_fx - vec4( 1.10000002E+00, 9.99999940E-02, -8.99999976E-01, 9.99999940E-02))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 7.99999952E-01); + _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0274); + _TMP275 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _fx45 = _TMP275*_TMP275*(3.00000000E+00 - 2.00000000E+00*_TMP275); + _x0284 = (_fx_left - vec4( 6.00000024E-01, 6.00000024E-01, -8.99999976E-01, -4.00000006E-01))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 8.00000012E-01); + _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0284); + _TMP285 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _fx30 = _TMP285*_TMP285*(3.00000000E+00 - 2.00000000E+00*_TMP285); + _x0294 = (_fx_up - vec4( 1.60000002E+00, -4.00000006E-01, -1.39999998E+00, 9.99999940E-02))/vec4( 8.00000072E-01, 8.00000012E-01, 7.99999952E-01, 7.99999952E-01); + _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0294); + _TMP295 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _fx60 = _TMP295*_TMP295*(3.00000000E+00 - 2.00000000E+00*_TMP295); + _x0304 = (_fx3_left - vec4( 4.59999990E+00, 2.59999990E+00, -3.40000010E+00, -1.39999998E+00))/vec4( 8.00000191E-01, 8.00000191E-01, 8.00000191E-01, 7.99999952E-01); + _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0304); + _TMP305 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _fx15 = _TMP305*_TMP305*(3.00000000E+00 - 2.00000000E+00*_TMP305); + _x0314 = (_fx3_up - vec4( 4.59999990E+00, -1.39999998E+00, -3.40000010E+00, 2.59999990E+00))/vec4( 8.00000191E-01, 7.99999952E-01, 8.00000191E-01, 8.00000191E-01); + _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0314); + _TMP315 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _fx75 = _TMP315*_TMP315*(3.00000000E+00 - 2.00000000E+00*_TMP315); + _a0326 = _r0142 - _r0132; + _TMP323 = abs(_a0326); + _a0330 = _r0142 - _r0132.zwxy; + _TMP327 = abs(_a0330); + _a0334 = _r0132.wxyz - _r0172; + _TMP331 = abs(_a0334); + _a0338 = _r0132.wxyz - _r0172.yzwx; + _TMP335 = abs(_a0338); + _a0342 = _r0122.zwxy - _r0122.wxyz; + _TMP339 = abs(_a0342); + _TMP36 = _TMP323 + _TMP327 + _TMP331 + _TMP335 + 4.00000000E+00*_TMP339; + _a0348 = _r0122.zwxy - _r0122.yzwx; + _TMP345 = abs(_a0348); + _a0352 = _r0122.zwxy - _r0162; + _TMP349 = abs(_a0352); + _a0356 = _r0122.wxyz - _r0152; + _TMP353 = abs(_a0356); + _a0360 = _r0122.wxyz - _r0122; + _TMP357 = abs(_a0360); + _a0364 = _r0142 - _r0132.wxyz; + _TMP361 = abs(_a0364); + _TMP37 = _TMP345 + _TMP349 + _TMP353 + _TMP357 + 4.00000000E+00*_TMP361; + _edr = bvec4(_TMP36.x < _TMP37.x && _interp_restriction_lv1.x, _TMP36.y < _TMP37.y && _interp_restriction_lv1.y, _TMP36.z < _TMP37.z && _interp_restriction_lv1.z, _TMP36.w < _TMP37.w && _interp_restriction_lv1.w); + _a0368 = _r0122.wxyz - _r0132.zwxy; + _TMP365 = abs(_a0368); + _a0372 = _r0122.zwxy - _r0132; + _TMP369 = abs(_a0372); + _edr_left = bvec4((2.00000000E+00*_TMP365).x <= _TMP369.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP365).y <= _TMP369.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP365).z <= _TMP369.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP365).w <= _TMP369.w && _interp_restriction_lv2_left.w); + _a0376 = _r0122.wxyz - _r0132.zwxy; + _TMP373 = abs(_a0376); + _a0380 = _r0122.zwxy - _r0132; + _TMP377 = abs(_a0380); + _edr_up = bvec4(_TMP373.x >= (2.00000000E+00*_TMP377).x && _interp_restriction_lv2_up.x, _TMP373.y >= (2.00000000E+00*_TMP377).y && _interp_restriction_lv2_up.y, _TMP373.z >= (2.00000000E+00*_TMP377).z && _interp_restriction_lv2_up.z, _TMP373.w >= (2.00000000E+00*_TMP377).w && _interp_restriction_lv2_up.w); + _nc45 = bvec4(_edr.x && bool(_fx45.x), _edr.y && bool(_fx45.y), _edr.z && bool(_fx45.z), _edr.w && bool(_fx45.w)); + _nc30 = bvec4(_edr.x && _edr_left.x && bool(_fx30.x), _edr.y && _edr_left.y && bool(_fx30.y), _edr.z && _edr_left.z && bool(_fx30.z), _edr.w && _edr_left.w && bool(_fx30.w)); + _nc60 = bvec4(_edr.x && _edr_up.x && bool(_fx60.x), _edr.y && _edr_up.y && bool(_fx60.y), _edr.z && _edr_up.z && bool(_fx60.z), _edr.w && _edr_up.w && bool(_fx60.w)); + _nc15 = bvec4(_edr.x && _edr_left.x && _interp_restriction_lv3_left.x && bool(_fx15.x), _edr.y && _edr_left.y && _interp_restriction_lv3_left.y && bool(_fx15.y), _edr.z && _edr_left.z && _interp_restriction_lv3_left.z && bool(_fx15.z), _edr.w && _edr_left.w && _interp_restriction_lv3_left.w && bool(_fx15.w)); + _nc75 = bvec4(_edr.x && _edr_up.x && _interp_restriction_lv3_up.x && bool(_fx75.x), _edr.y && _edr_up.y && _interp_restriction_lv3_up.y && bool(_fx75.y), _edr.z && _edr_up.z && _interp_restriction_lv3_up.z && bool(_fx75.z), _edr.w && _edr_up.w && _interp_restriction_lv3_up.w && bool(_fx75.w)); + _a0384 = _r0142 - _r0122.wxyz; + _TMP381 = abs(_a0384); + _a0388 = _r0142 - _r0122.zwxy; + _TMP385 = abs(_a0388); + _px = bvec4(_TMP381.x <= _TMP385.x, _TMP381.y <= _TMP385.y, _TMP381.z <= _TMP385.z, _TMP381.w <= _TMP385.w); + _nc = bvec4(_nc75.x || _nc15.x || _nc30.x || _nc60.x || _nc45.x, _nc75.y || _nc15.y || _nc30.y || _nc60.y || _nc45.y, _nc75.z || _nc15.z || _nc30.z || _nc60.z || _nc45.z, _nc75.w || _nc15.w || _nc30.w || _nc60.w || _nc45.w); + _final45 = vec4(float(_nc45.x), float(_nc45.y), float(_nc45.z), float(_nc45.w))*_fx45; + _final30 = vec4(float(_nc30.x), float(_nc30.y), float(_nc30.z), float(_nc30.w))*_fx30; + _final60 = vec4(float(_nc60.x), float(_nc60.y), float(_nc60.z), float(_nc60.w))*_fx60; + _final15 = vec4(float(_nc15.x), float(_nc15.y), float(_nc15.z), float(_nc15.w))*_fx15; + _final75 = vec4(float(_nc75.x), float(_nc75.y), float(_nc75.z), float(_nc75.w))*_fx75; + _TMP44 = max(_final15, _final75); + _TMP45 = max(_final30, _final60); + _TMP46 = max(_TMP44, _TMP45); + _maximo = max(_TMP46, _final45); + if (_nc.x) { + if (_px.x) { + _TMP47 = _TMP8.xyz; + } else { + _TMP47 = _TMP10.xyz; + } + _pix1 = _TMP47; + _blend1 = _maximo.x; + } else { + if (_nc.y) { + if (_px.y) { + _TMP48 = _TMP4.xyz; + } else { + _TMP48 = _TMP8.xyz; + } + _pix1 = _TMP48; + _blend1 = _maximo.y; + } else { + if (_nc.z) { + if (_px.z) { + _TMP49 = _TMP6.xyz; + } else { + _TMP49 = _TMP4.xyz; + } + _pix1 = _TMP49; + _blend1 = _maximo.z; + } else { + if (_nc.w) { + if (_px.w) { + _TMP50 = _TMP10.xyz; + } else { + _TMP50 = _TMP6.xyz; + } + _pix1 = _TMP50; + _blend1 = _maximo.w; + } + } + } + } + if (_nc.w) { + if (_px.w) { + _TMP51 = _TMP10.xyz; + } else { + _TMP51 = _TMP6.xyz; + } + _pix2 = _TMP51; + _blend2 = _maximo.w; + } else { + if (_nc.z) { + if (_px.z) { + _TMP52 = _TMP6.xyz; + } else { + _TMP52 = _TMP4.xyz; + } + _pix2 = _TMP52; + _blend2 = _maximo.z; + } else { + if (_nc.y) { + if (_px.y) { + _TMP53 = _TMP4.xyz; + } else { + _TMP53 = _TMP8.xyz; + } + _pix2 = _TMP53; + _blend2 = _maximo.y; + } else { + if (_nc.x) { + if (_px.x) { + _TMP54 = _TMP8.xyz; + } else { + _TMP54 = _TMP10.xyz; + } + _pix2 = _TMP54; + _blend2 = _maximo.x; + } + } + } + } + _res1 = _TMP7.xyz + _blend1*(_pix1 - _TMP7.xyz); + _res2 = _TMP7.xyz + _blend2*(_pix2 - _TMP7.xyz); + _a0404 = _TMP7.xyz - _res1; + _df0402 = abs(_a0404); + _TMP55 = _df0402.x + _df0402.y + _df0402.z; + _a0408 = _TMP7.xyz - _res2; + _df0406 = abs(_a0408); + _TMP56 = _df0406.x + _df0406.y + _df0406.z; + _TMP57 = float((_TMP56 >= _TMP55)); + _res = _res1 + _TMP57*(_res2 - _res1); + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} diff --git a/res/shaders/xbr.shader/xbr.vs b/res/shaders/xbr.shader/xbr.vs new file mode 100644 index 000000000..6a9526ac7 --- /dev/null +++ b/res/shaders/xbr.shader/xbr.vs @@ -0,0 +1,78 @@ +/* + Hyllian's xBR-lv3 Shader + + Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + + Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. +*/ +// GLSL shader autogenerated by cg2glsl.py. +#if __VERSION__ >= 130 +#define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in +#define COMPAT_TEXTURE texture +#else +#define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +vec4 _r0007; +COMPAT_ATTRIBUTE vec4 position; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; +const COMPAT_PRECISION vec2 TextureSize = vec2(240.0, 160.0); + +void main() +{ + vec2 _ps; + vec2 _texCoord; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5) + vec2( 1.00000001E-07, 1.00000001E-07); + gl_Position = position; + TEX0.xy = _texCoord; + TEX1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + TEX2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + TEX3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + TEX4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + TEX5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + TEX6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + TEX7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); +} From d07da0744cfb5aff43ae9aff6a7b97c2b9e874d9 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 15:41:45 -0800 Subject: [PATCH 35/68] Shaders: Minor xBR fixes --- res/shaders/xbr.shader/manifest.ini | 1 + res/shaders/xbr.shader/xbr.fs | 7 ------- res/shaders/xbr.shader/xbr.vs | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/res/shaders/xbr.shader/manifest.ini b/res/shaders/xbr.shader/manifest.ini index a070badbd..d25360da3 100644 --- a/res/shaders/xbr.shader/manifest.ini +++ b/res/shaders/xbr.shader/manifest.ini @@ -1,6 +1,7 @@ [shader] name=xBR author=Hyllian +description=xBR upsampling filter passes=1 [pass.0] diff --git a/res/shaders/xbr.shader/xbr.fs b/res/shaders/xbr.shader/xbr.fs index 72f726e4d..43e79de6a 100644 --- a/res/shaders/xbr.shader/xbr.fs +++ b/res/shaders/xbr.shader/xbr.fs @@ -45,13 +45,6 @@ precision mediump float; #else #define COMPAT_PRECISION #endif -COMPAT_VARYING vec4 _t7; -COMPAT_VARYING vec4 _t6; -COMPAT_VARYING vec4 _t5; -COMPAT_VARYING vec4 _t4; -COMPAT_VARYING vec4 _t3; -COMPAT_VARYING vec4 _t2; -COMPAT_VARYING vec4 _t1; vec4 _ret_0; float _TMP57; float _TMP56; diff --git a/res/shaders/xbr.shader/xbr.vs b/res/shaders/xbr.shader/xbr.vs index 6a9526ac7..01033d557 100644 --- a/res/shaders/xbr.shader/xbr.vs +++ b/res/shaders/xbr.shader/xbr.vs @@ -49,7 +49,6 @@ COMPAT_VARYING vec4 _t2; COMPAT_VARYING vec4 _t1; vec4 _r0007; COMPAT_ATTRIBUTE vec4 position; -COMPAT_VARYING vec4 COL0; COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec4 TEX1; COMPAT_VARYING vec4 TEX2; From 3d996caf533cd55badf30f328f1a1f5fb72d450f Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 15:45:39 -0800 Subject: [PATCH 36/68] Shaders: Hand-convert xBR shader to GLSL --- res/shaders/xbr.shader/xbr.fs | 654 +++++++++++----------------------- res/shaders/xbr.shader/xbr.vs | 79 ++-- 2 files changed, 232 insertions(+), 501 deletions(-) diff --git a/res/shaders/xbr.shader/xbr.fs b/res/shaders/xbr.shader/xbr.fs index 43e79de6a..dcd779586 100644 --- a/res/shaders/xbr.shader/xbr.fs +++ b/res/shaders/xbr.shader/xbr.fs @@ -24,13 +24,56 @@ Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. */ + +#define XBR_Y_WEIGHT 48.0 +#define XBR_EQ_THRESHOLD 10.0 +#define XBR_EQ_THRESHOLD2 2.0 +#define XBR_LV2_COEFFICIENT 2.0 + +const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813); +const vec4 delta = vec4(0.4, 0.4, 0.4, 0.4); + +vec4 df(vec4 A, vec4 B) +{ + return vec4(abs(A-B)); +} + +float c_df(vec3 c1, vec3 c2) { + vec3 df = abs(c1 - c2); + return df.r + df.g + df.b; +} + +bvec4 eq(vec4 A, vec4 B) +{ + return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD)); +} + +bvec4 eq2(vec4 A, vec4 B) +{ + return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD2)); +} + +bvec4 and(bvec4 A, bvec4 B) +{ + return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w); +} + +bvec4 or(bvec4 A, bvec4 B) +{ + return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w); +} + +vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) +{ + return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); +} + // GLSL shader autogenerated by cg2glsl.py. #if __VERSION__ >= 130 -#define COMPAT_VARYING in +#define varying in #define COMPAT_TEXTURE texture out vec4 FragColor; #else -#define COMPAT_VARYING varying #define FragColor gl_FragColor #define COMPAT_TEXTURE texture2D #endif @@ -45,459 +88,164 @@ precision mediump float; #else #define COMPAT_PRECISION #endif -vec4 _ret_0; -float _TMP57; -float _TMP56; -float _TMP55; -vec3 _TMP54; -vec3 _TMP53; -vec3 _TMP52; -vec3 _TMP51; -vec3 _TMP50; -vec3 _TMP49; -vec3 _TMP48; -vec3 _TMP47; -vec4 _TMP46; -vec4 _TMP45; -vec4 _TMP44; -vec4 _TMP37; -vec4 _TMP36; -vec4 _TMP65; -bvec4 _TMP35; -bvec4 _TMP34; -bvec4 _TMP33; -bvec4 _TMP32; -bvec4 _TMP31; -bvec4 _TMP30; -bvec4 _TMP29; -bvec4 _TMP28; -bvec4 _TMP27; -bvec4 _TMP26; -bvec4 _TMP25; -bvec4 _TMP24; -bvec4 _TMP23; -bvec4 _TMP22; -bvec4 _TMP21; -vec4 _TMP20; -vec4 _TMP19; -vec4 _TMP18; -vec4 _TMP17; -vec4 _TMP16; -vec4 _TMP15; -vec4 _TMP14; -vec4 _TMP13; -vec4 _TMP12; -vec4 _TMP11; -vec4 _TMP10; -vec4 _TMP9; -vec4 _TMP8; -vec4 _TMP7; -vec4 _TMP6; -vec4 _TMP5; -vec4 _TMP4; -vec4 _TMP3; -vec4 _TMP2; -vec4 _TMP1; -vec4 _TMP0; uniform sampler2D tex; -vec2 _x0078; -vec4 _r0122; -vec4 _r0132; -vec4 _r0142; -vec4 _r0152; -vec4 _r0162; -vec4 _r0172; -vec4 _TMP183; -vec4 _a0186; -vec4 _TMP189; -vec4 _a0192; -vec4 _TMP195; -vec4 _a0198; -vec4 _TMP201; -vec4 _a0204; -vec4 _TMP207; -vec4 _a0210; -vec4 _TMP213; -vec4 _a0216; -vec4 _TMP219; -vec4 _a0222; -vec4 _TMP225; -vec4 _a0228; -vec4 _TMP231; -vec4 _a0234; -vec4 _TMP237; -vec4 _a0240; -vec4 _TMP243; -vec4 _a0246; -vec4 _TMP249; -vec4 _a0252; -vec4 _TMP255; -vec4 _a0258; -vec4 _TMP261; -vec4 _a0264; -vec4 _TMP267; -vec4 _a0270; -vec4 _x0274; -vec4 _TMP275; -vec4 _x0284; -vec4 _TMP285; -vec4 _x0294; -vec4 _TMP295; -vec4 _x0304; -vec4 _TMP305; -vec4 _x0314; -vec4 _TMP315; -vec4 _TMP323; -vec4 _a0326; -vec4 _TMP327; -vec4 _a0330; -vec4 _TMP331; -vec4 _a0334; -vec4 _TMP335; -vec4 _a0338; -vec4 _TMP339; -vec4 _a0342; -vec4 _TMP345; -vec4 _a0348; -vec4 _TMP349; -vec4 _a0352; -vec4 _TMP353; -vec4 _a0356; -vec4 _TMP357; -vec4 _a0360; -vec4 _TMP361; -vec4 _a0364; -vec4 _TMP365; -vec4 _a0368; -vec4 _TMP369; -vec4 _a0372; -vec4 _TMP373; -vec4 _a0376; -vec4 _TMP377; -vec4 _a0380; -vec4 _TMP381; -vec4 _a0384; -vec4 _TMP385; -vec4 _a0388; -vec3 _df0402; -vec3 _a0404; -vec3 _df0406; -vec3 _a0408; -COMPAT_VARYING vec4 TEX0; -COMPAT_VARYING vec4 TEX1; -COMPAT_VARYING vec4 TEX2; -COMPAT_VARYING vec4 TEX3; -COMPAT_VARYING vec4 TEX4; -COMPAT_VARYING vec4 TEX5; -COMPAT_VARYING vec4 TEX6; -COMPAT_VARYING vec4 TEX7; +varying vec2 texCoord; +varying vec4 TEX1; +varying vec4 TEX2; +varying vec4 TEX3; +varying vec4 TEX4; +varying vec4 TEX5; +varying vec4 TEX6; +varying vec4 TEX7; + +const vec2 TextureSize = vec2(240.0, 160.0); -const COMPAT_PRECISION vec2 TextureSize = vec2(240.0, 160.0); void main() { - bvec4 _edr; - bvec4 _edr_left; - bvec4 _edr_up; - bvec4 _px; - bvec4 _interp_restriction_lv1; - bvec4 _interp_restriction_lv2_left; - bvec4 _interp_restriction_lv2_up; - bvec4 _interp_restriction_lv3_left; - bvec4 _interp_restriction_lv3_up; - bvec4 _nc; - bvec4 _nc30; - bvec4 _nc60; - bvec4 _nc45; - bvec4 _nc15; - bvec4 _nc75; - vec4 _fx; - vec4 _fx_left; - vec4 _fx_up; - vec4 _fx3_left; - vec4 _fx3_up; - vec3 _res1; - vec3 _res2; - vec3 _pix1; - vec3 _pix2; - float _blend1; - float _blend2; - vec2 _fp; - vec4 _fx45; - vec4 _fx30; - vec4 _fx60; - vec4 _fx15; - vec4 _fx75; - vec4 _final45; - vec4 _final30; - vec4 _final60; - vec4 _final15; - vec4 _final75; - vec4 _maximo; - vec3 _res; - _x0078 = TEX0.xy*TextureSize; - _fp = fract(_x0078); - _TMP0 = COMPAT_TEXTURE(tex, TEX1.xw); - _TMP1 = COMPAT_TEXTURE(tex, TEX1.yw); - _TMP2 = COMPAT_TEXTURE(tex, TEX1.zw); - _TMP3 = COMPAT_TEXTURE(tex, TEX2.xw); - _TMP4 = COMPAT_TEXTURE(tex, TEX2.yw); - _TMP5 = COMPAT_TEXTURE(tex, TEX2.zw); - _TMP6 = COMPAT_TEXTURE(tex, TEX3.xw); - _TMP7 = COMPAT_TEXTURE(tex, TEX3.yw); - _TMP8 = COMPAT_TEXTURE(tex, TEX3.zw); - _TMP9 = COMPAT_TEXTURE(tex, TEX4.xw); - _TMP10 = COMPAT_TEXTURE(tex, TEX4.yw); - _TMP11 = COMPAT_TEXTURE(tex, TEX4.zw); - _TMP12 = COMPAT_TEXTURE(tex, TEX5.xw); - _TMP13 = COMPAT_TEXTURE(tex, TEX5.yw); - _TMP14 = COMPAT_TEXTURE(tex, TEX5.zw); - _TMP15 = COMPAT_TEXTURE(tex, TEX6.xy); - _TMP16 = COMPAT_TEXTURE(tex, TEX6.xz); - _TMP17 = COMPAT_TEXTURE(tex, TEX6.xw); - _TMP18 = COMPAT_TEXTURE(tex, TEX7.xy); - _TMP19 = COMPAT_TEXTURE(tex, TEX7.xz); - _TMP20 = COMPAT_TEXTURE(tex, TEX7.xw); - _r0122.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0122.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0122.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0122.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0132.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0132.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0132.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0132.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0142.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0142.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0142.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0142.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0152.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0152.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0152.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0152.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0162.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0162.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0162.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0162.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0172.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0172.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0172.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _r0172.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); - _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; - _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; - _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; - _fx3_left = vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x; - _fx3_up = vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x; - _a0186 = _r0122.wxyz - _r0122; - _TMP183 = abs(_a0186); - _TMP21 = bvec4(_TMP183.x < 1.00000000E+01, _TMP183.y < 1.00000000E+01, _TMP183.z < 1.00000000E+01, _TMP183.w < 1.00000000E+01); - _a0192 = _r0122.wxyz - _r0132; - _TMP189 = abs(_a0192); - _TMP22 = bvec4(_TMP189.x < 1.00000000E+01, _TMP189.y < 1.00000000E+01, _TMP189.z < 1.00000000E+01, _TMP189.w < 1.00000000E+01); - _a0198 = _r0122.zwxy - _r0122.yzwx; - _TMP195 = abs(_a0198); - _TMP23 = bvec4(_TMP195.x < 1.00000000E+01, _TMP195.y < 1.00000000E+01, _TMP195.z < 1.00000000E+01, _TMP195.w < 1.00000000E+01); - _a0204 = _r0122.zwxy - _r0132.zwxy; - _TMP201 = abs(_a0204); - _TMP24 = bvec4(_TMP201.x < 1.00000000E+01, _TMP201.y < 1.00000000E+01, _TMP201.z < 1.00000000E+01, _TMP201.w < 1.00000000E+01); - _a0210 = _r0142 - _r0132.wxyz; - _TMP207 = abs(_a0210); - _TMP25 = bvec4(_TMP207.x < 1.00000000E+01, _TMP207.y < 1.00000000E+01, _TMP207.z < 1.00000000E+01, _TMP207.w < 1.00000000E+01); - _a0216 = _r0122.wxyz - _r0172.yzwx; - _TMP213 = abs(_a0216); - _TMP26 = bvec4(_TMP213.x < 1.00000000E+01, _TMP213.y < 1.00000000E+01, _TMP213.z < 1.00000000E+01, _TMP213.w < 1.00000000E+01); - _a0222 = _r0122.wxyz - _r0152; - _TMP219 = abs(_a0222); - _TMP27 = bvec4(_TMP219.x < 1.00000000E+01, _TMP219.y < 1.00000000E+01, _TMP219.z < 1.00000000E+01, _TMP219.w < 1.00000000E+01); - _a0228 = _r0122.zwxy - _r0172; - _TMP225 = abs(_a0228); - _TMP28 = bvec4(_TMP225.x < 1.00000000E+01, _TMP225.y < 1.00000000E+01, _TMP225.z < 1.00000000E+01, _TMP225.w < 1.00000000E+01); - _a0234 = _r0122.zwxy - _r0162; - _TMP231 = abs(_a0234); - _TMP29 = bvec4(_TMP231.x < 1.00000000E+01, _TMP231.y < 1.00000000E+01, _TMP231.z < 1.00000000E+01, _TMP231.w < 1.00000000E+01); - _a0240 = _r0142 - _r0132.zwxy; - _TMP237 = abs(_a0240); - _TMP30 = bvec4(_TMP237.x < 1.00000000E+01, _TMP237.y < 1.00000000E+01, _TMP237.z < 1.00000000E+01, _TMP237.w < 1.00000000E+01); - _a0246 = _r0142 - _r0132; - _TMP243 = abs(_a0246); - _TMP31 = bvec4(_TMP243.x < 1.00000000E+01, _TMP243.y < 1.00000000E+01, _TMP243.z < 1.00000000E+01, _TMP243.w < 1.00000000E+01); - _interp_restriction_lv1 = bvec4(_r0142.x != _r0122.w && _r0142.x != _r0122.z && (!_TMP21.x && !_TMP22.x || !_TMP23.x && !_TMP24.x || _TMP25.x && (!_TMP26.x && !_TMP27.x || !_TMP28.x && !_TMP29.x) || _TMP30.x || _TMP31.x), _r0142.y != _r0122.x && _r0142.y != _r0122.w && (!_TMP21.y && !_TMP22.y || !_TMP23.y && !_TMP24.y || _TMP25.y && (!_TMP26.y && !_TMP27.y || !_TMP28.y && !_TMP29.y) || _TMP30.y || _TMP31.y), _r0142.z != _r0122.y && _r0142.z != _r0122.x && (!_TMP21.z && !_TMP22.z || !_TMP23.z && !_TMP24.z || _TMP25.z && (!_TMP26.z && !_TMP27.z || !_TMP28.z && !_TMP29.z) || _TMP30.z || _TMP31.z), _r0142.w != _r0122.z && _r0142.w != _r0122.y && (!_TMP21.w && !_TMP22.w || !_TMP23.w && !_TMP24.w || _TMP25.w && (!_TMP26.w && !_TMP27.w || !_TMP28.w && !_TMP29.w) || _TMP30.w || _TMP31.w)); - _interp_restriction_lv2_left = bvec4(_r0142.x != _r0132.z && _r0122.y != _r0132.z, _r0142.y != _r0132.w && _r0122.z != _r0132.w, _r0142.z != _r0132.x && _r0122.w != _r0132.x, _r0142.w != _r0132.y && _r0122.x != _r0132.y); - _interp_restriction_lv2_up = bvec4(_r0142.x != _r0132.x && _r0122.x != _r0132.x, _r0142.y != _r0132.y && _r0122.y != _r0132.y, _r0142.z != _r0132.z && _r0122.z != _r0132.z, _r0142.w != _r0132.w && _r0122.w != _r0132.w); - _a0252 = _r0132.zwxy - _r0162.wxyz; - _TMP249 = abs(_a0252); - _TMP32 = bvec4(_TMP249.x < 2.00000000E+00, _TMP249.y < 2.00000000E+00, _TMP249.z < 2.00000000E+00, _TMP249.w < 2.00000000E+00); - _a0258 = _r0172.wxyz - _r0162.wxyz; - _TMP255 = abs(_a0258); - _TMP33 = bvec4(_TMP255.x < 2.00000000E+00, _TMP255.y < 2.00000000E+00, _TMP255.z < 2.00000000E+00, _TMP255.w < 2.00000000E+00); - _interp_restriction_lv3_left = bvec4(_TMP32.x && !_TMP33.x, _TMP32.y && !_TMP33.y, _TMP32.z && !_TMP33.z, _TMP32.w && !_TMP33.w); - _a0264 = _r0132 - _r0152.yzwx; - _TMP261 = abs(_a0264); - _TMP34 = bvec4(_TMP261.x < 2.00000000E+00, _TMP261.y < 2.00000000E+00, _TMP261.z < 2.00000000E+00, _TMP261.w < 2.00000000E+00); - _a0270 = _r0172.zwxy - _r0152.yzwx; - _TMP267 = abs(_a0270); - _TMP35 = bvec4(_TMP267.x < 2.00000000E+00, _TMP267.y < 2.00000000E+00, _TMP267.z < 2.00000000E+00, _TMP267.w < 2.00000000E+00); - _interp_restriction_lv3_up = bvec4(_TMP34.x && !_TMP35.x, _TMP34.y && !_TMP35.y, _TMP34.z && !_TMP35.z, _TMP34.w && !_TMP35.w); - _x0274 = (_fx - vec4( 1.10000002E+00, 9.99999940E-02, -8.99999976E-01, 9.99999940E-02))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 7.99999952E-01); - _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0274); - _TMP275 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); - _fx45 = _TMP275*_TMP275*(3.00000000E+00 - 2.00000000E+00*_TMP275); - _x0284 = (_fx_left - vec4( 6.00000024E-01, 6.00000024E-01, -8.99999976E-01, -4.00000006E-01))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 8.00000012E-01); - _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0284); - _TMP285 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); - _fx30 = _TMP285*_TMP285*(3.00000000E+00 - 2.00000000E+00*_TMP285); - _x0294 = (_fx_up - vec4( 1.60000002E+00, -4.00000006E-01, -1.39999998E+00, 9.99999940E-02))/vec4( 8.00000072E-01, 8.00000012E-01, 7.99999952E-01, 7.99999952E-01); - _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0294); - _TMP295 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); - _fx60 = _TMP295*_TMP295*(3.00000000E+00 - 2.00000000E+00*_TMP295); - _x0304 = (_fx3_left - vec4( 4.59999990E+00, 2.59999990E+00, -3.40000010E+00, -1.39999998E+00))/vec4( 8.00000191E-01, 8.00000191E-01, 8.00000191E-01, 7.99999952E-01); - _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0304); - _TMP305 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); - _fx15 = _TMP305*_TMP305*(3.00000000E+00 - 2.00000000E+00*_TMP305); - _x0314 = (_fx3_up - vec4( 4.59999990E+00, -1.39999998E+00, -3.40000010E+00, 2.59999990E+00))/vec4( 8.00000191E-01, 7.99999952E-01, 8.00000191E-01, 8.00000191E-01); - _TMP65 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0314); - _TMP315 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); - _fx75 = _TMP315*_TMP315*(3.00000000E+00 - 2.00000000E+00*_TMP315); - _a0326 = _r0142 - _r0132; - _TMP323 = abs(_a0326); - _a0330 = _r0142 - _r0132.zwxy; - _TMP327 = abs(_a0330); - _a0334 = _r0132.wxyz - _r0172; - _TMP331 = abs(_a0334); - _a0338 = _r0132.wxyz - _r0172.yzwx; - _TMP335 = abs(_a0338); - _a0342 = _r0122.zwxy - _r0122.wxyz; - _TMP339 = abs(_a0342); - _TMP36 = _TMP323 + _TMP327 + _TMP331 + _TMP335 + 4.00000000E+00*_TMP339; - _a0348 = _r0122.zwxy - _r0122.yzwx; - _TMP345 = abs(_a0348); - _a0352 = _r0122.zwxy - _r0162; - _TMP349 = abs(_a0352); - _a0356 = _r0122.wxyz - _r0152; - _TMP353 = abs(_a0356); - _a0360 = _r0122.wxyz - _r0122; - _TMP357 = abs(_a0360); - _a0364 = _r0142 - _r0132.wxyz; - _TMP361 = abs(_a0364); - _TMP37 = _TMP345 + _TMP349 + _TMP353 + _TMP357 + 4.00000000E+00*_TMP361; - _edr = bvec4(_TMP36.x < _TMP37.x && _interp_restriction_lv1.x, _TMP36.y < _TMP37.y && _interp_restriction_lv1.y, _TMP36.z < _TMP37.z && _interp_restriction_lv1.z, _TMP36.w < _TMP37.w && _interp_restriction_lv1.w); - _a0368 = _r0122.wxyz - _r0132.zwxy; - _TMP365 = abs(_a0368); - _a0372 = _r0122.zwxy - _r0132; - _TMP369 = abs(_a0372); - _edr_left = bvec4((2.00000000E+00*_TMP365).x <= _TMP369.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP365).y <= _TMP369.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP365).z <= _TMP369.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP365).w <= _TMP369.w && _interp_restriction_lv2_left.w); - _a0376 = _r0122.wxyz - _r0132.zwxy; - _TMP373 = abs(_a0376); - _a0380 = _r0122.zwxy - _r0132; - _TMP377 = abs(_a0380); - _edr_up = bvec4(_TMP373.x >= (2.00000000E+00*_TMP377).x && _interp_restriction_lv2_up.x, _TMP373.y >= (2.00000000E+00*_TMP377).y && _interp_restriction_lv2_up.y, _TMP373.z >= (2.00000000E+00*_TMP377).z && _interp_restriction_lv2_up.z, _TMP373.w >= (2.00000000E+00*_TMP377).w && _interp_restriction_lv2_up.w); - _nc45 = bvec4(_edr.x && bool(_fx45.x), _edr.y && bool(_fx45.y), _edr.z && bool(_fx45.z), _edr.w && bool(_fx45.w)); - _nc30 = bvec4(_edr.x && _edr_left.x && bool(_fx30.x), _edr.y && _edr_left.y && bool(_fx30.y), _edr.z && _edr_left.z && bool(_fx30.z), _edr.w && _edr_left.w && bool(_fx30.w)); - _nc60 = bvec4(_edr.x && _edr_up.x && bool(_fx60.x), _edr.y && _edr_up.y && bool(_fx60.y), _edr.z && _edr_up.z && bool(_fx60.z), _edr.w && _edr_up.w && bool(_fx60.w)); - _nc15 = bvec4(_edr.x && _edr_left.x && _interp_restriction_lv3_left.x && bool(_fx15.x), _edr.y && _edr_left.y && _interp_restriction_lv3_left.y && bool(_fx15.y), _edr.z && _edr_left.z && _interp_restriction_lv3_left.z && bool(_fx15.z), _edr.w && _edr_left.w && _interp_restriction_lv3_left.w && bool(_fx15.w)); - _nc75 = bvec4(_edr.x && _edr_up.x && _interp_restriction_lv3_up.x && bool(_fx75.x), _edr.y && _edr_up.y && _interp_restriction_lv3_up.y && bool(_fx75.y), _edr.z && _edr_up.z && _interp_restriction_lv3_up.z && bool(_fx75.z), _edr.w && _edr_up.w && _interp_restriction_lv3_up.w && bool(_fx75.w)); - _a0384 = _r0142 - _r0122.wxyz; - _TMP381 = abs(_a0384); - _a0388 = _r0142 - _r0122.zwxy; - _TMP385 = abs(_a0388); - _px = bvec4(_TMP381.x <= _TMP385.x, _TMP381.y <= _TMP385.y, _TMP381.z <= _TMP385.z, _TMP381.w <= _TMP385.w); - _nc = bvec4(_nc75.x || _nc15.x || _nc30.x || _nc60.x || _nc45.x, _nc75.y || _nc15.y || _nc30.y || _nc60.y || _nc45.y, _nc75.z || _nc15.z || _nc30.z || _nc60.z || _nc45.z, _nc75.w || _nc15.w || _nc30.w || _nc60.w || _nc45.w); - _final45 = vec4(float(_nc45.x), float(_nc45.y), float(_nc45.z), float(_nc45.w))*_fx45; - _final30 = vec4(float(_nc30.x), float(_nc30.y), float(_nc30.z), float(_nc30.w))*_fx30; - _final60 = vec4(float(_nc60.x), float(_nc60.y), float(_nc60.z), float(_nc60.w))*_fx60; - _final15 = vec4(float(_nc15.x), float(_nc15.y), float(_nc15.z), float(_nc15.w))*_fx15; - _final75 = vec4(float(_nc75.x), float(_nc75.y), float(_nc75.z), float(_nc75.w))*_fx75; - _TMP44 = max(_final15, _final75); - _TMP45 = max(_final30, _final60); - _TMP46 = max(_TMP44, _TMP45); - _maximo = max(_TMP46, _final45); - if (_nc.x) { - if (_px.x) { - _TMP47 = _TMP8.xyz; - } else { - _TMP47 = _TMP10.xyz; - } - _pix1 = _TMP47; - _blend1 = _maximo.x; - } else { - if (_nc.y) { - if (_px.y) { - _TMP48 = _TMP4.xyz; - } else { - _TMP48 = _TMP8.xyz; - } - _pix1 = _TMP48; - _blend1 = _maximo.y; - } else { - if (_nc.z) { - if (_px.z) { - _TMP49 = _TMP6.xyz; - } else { - _TMP49 = _TMP4.xyz; - } - _pix1 = _TMP49; - _blend1 = _maximo.z; - } else { - if (_nc.w) { - if (_px.w) { - _TMP50 = _TMP10.xyz; - } else { - _TMP50 = _TMP6.xyz; - } - _pix1 = _TMP50; - _blend1 = _maximo.w; - } - } - } - } - if (_nc.w) { - if (_px.w) { - _TMP51 = _TMP10.xyz; - } else { - _TMP51 = _TMP6.xyz; - } - _pix2 = _TMP51; - _blend2 = _maximo.w; - } else { - if (_nc.z) { - if (_px.z) { - _TMP52 = _TMP6.xyz; - } else { - _TMP52 = _TMP4.xyz; - } - _pix2 = _TMP52; - _blend2 = _maximo.z; - } else { - if (_nc.y) { - if (_px.y) { - _TMP53 = _TMP4.xyz; - } else { - _TMP53 = _TMP8.xyz; - } - _pix2 = _TMP53; - _blend2 = _maximo.y; - } else { - if (_nc.x) { - if (_px.x) { - _TMP54 = _TMP8.xyz; - } else { - _TMP54 = _TMP10.xyz; - } - _pix2 = _TMP54; - _blend2 = _maximo.x; - } - } - } - } - _res1 = _TMP7.xyz + _blend1*(_pix1 - _TMP7.xyz); - _res2 = _TMP7.xyz + _blend2*(_pix2 - _TMP7.xyz); - _a0404 = _TMP7.xyz - _res1; - _df0402 = abs(_a0404); - _TMP55 = _df0402.x + _df0402.y + _df0402.z; - _a0408 = _TMP7.xyz - _res2; - _df0406 = abs(_a0408); - _TMP56 = _df0406.x + _df0406.y + _df0406.z; - _TMP57 = float((_TMP56 >= _TMP55)); - _res = _res1 + _TMP57*(_res2 - _res1); - _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); - FragColor = _ret_0; - return; + bvec4 edr, edr_left, edr_up, edr3_left, edr3_up, px; // px = pixel, edr = edge detection rule + bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up; + bvec4 interp_restriction_lv3_left, interp_restriction_lv3_up; + bvec4 nc, nc30, nc60, nc45, nc15, nc75; // new_color + vec4 fx, fx_left, fx_up, finalfx, fx3_left, fx3_up; // inequations of straight lines. + vec3 res1, res2, pix1, pix2; + float blend1, blend2; + + vec2 fp = fract(texCoord * TextureSize); + + vec3 A1 = COMPAT_TEXTURE(tex, TEX1.xw).rgb; + vec3 B1 = COMPAT_TEXTURE(tex, TEX1.yw).rgb; + vec3 C1 = COMPAT_TEXTURE(tex, TEX1.zw).rgb; + + vec3 A = COMPAT_TEXTURE(tex, TEX2.xw).rgb; + vec3 B = COMPAT_TEXTURE(tex, TEX2.yw).rgb; + vec3 C = COMPAT_TEXTURE(tex, TEX2.zw).rgb; + + vec3 D = COMPAT_TEXTURE(tex, TEX3.xw).rgb; + vec3 E = COMPAT_TEXTURE(tex, TEX3.yw).rgb; + vec3 F = COMPAT_TEXTURE(tex, TEX3.zw).rgb; + + vec3 G = COMPAT_TEXTURE(tex, TEX4.xw).rgb; + vec3 H = COMPAT_TEXTURE(tex, TEX4.yw).rgb; + vec3 I = COMPAT_TEXTURE(tex, TEX4.zw).rgb; + + vec3 G5 = COMPAT_TEXTURE(tex, TEX5.xw).rgb; + vec3 H5 = COMPAT_TEXTURE(tex, TEX5.yw).rgb; + vec3 I5 = COMPAT_TEXTURE(tex, TEX5.zw).rgb; + + vec3 A0 = COMPAT_TEXTURE(tex, TEX6.xy).rgb; + vec3 D0 = COMPAT_TEXTURE(tex, TEX6.xz).rgb; + vec3 G0 = COMPAT_TEXTURE(tex, TEX6.xw).rgb; + + vec3 C4 = COMPAT_TEXTURE(tex, TEX7.xy).rgb; + vec3 F4 = COMPAT_TEXTURE(tex, TEX7.xz).rgb; + vec3 I4 = COMPAT_TEXTURE(tex, TEX7.xw).rgb; + + vec4 b = transpose(mat4x3(B, D, H, F)) * (XBR_Y_WEIGHT * yuv[0]); + vec4 c = transpose(mat4x3(C, A, G, I)) * (XBR_Y_WEIGHT * yuv[0]); + vec4 e = transpose(mat4x3(E, E, E, E)) * (XBR_Y_WEIGHT * yuv[0]); + vec4 d = b.yzwx; + vec4 f = b.wxyz; + vec4 g = c.zwxy; + vec4 h = b.zwxy; + vec4 i = c.wxyz; + + vec4 i4 = transpose(mat4x3(I4, C1, A0, G5)) * (XBR_Y_WEIGHT*yuv[0]); + vec4 i5 = transpose(mat4x3(I5, C4, A1, G0)) * (XBR_Y_WEIGHT*yuv[0]); + vec4 h5 = transpose(mat4x3(H5, F4, B1, D0)) * (XBR_Y_WEIGHT*yuv[0]); + vec4 f4 = h5.yzwx; + + vec4 c1 = i4.yzwx; + vec4 g0 = i5.wxyz; + vec4 b1 = h5.zwxy; + vec4 d0 = h5.wxyz; + + vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 ); + vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 ); + vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 ); + vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 ); + vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 ); + vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 ); + vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 ); + vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 ); + vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 ); + + vec4 Az = vec4( 6.0, -2.0, -6.0, 2.0 ); + vec4 Bz = vec4( 2.0, 6.0, -2.0, -6.0 ); + vec4 Cz = vec4( 5.0, 3.0, -3.0, -1.0 ); + vec4 Aw = vec4( 2.0, -6.0, -2.0, 6.0 ); + vec4 Bw = vec4( 6.0, 2.0, -6.0,-2.0 ); + vec4 Cw = vec4( 5.0, -1.0, -3.0, 3.0 ); + + fx = (Ao*fp.y+Bo*fp.x); + fx_left = (Ax*fp.y+Bx*fp.x); + fx_up = (Ay*fp.y+By*fp.x); + fx3_left= (Az*fp.y+Bz*fp.x); + fx3_up = (Aw*fp.y+Bw*fp.x); + + // It uses CORNER_C if none of the others are defined. +#ifdef CORNER_A + interp_restriction_lv1 = and(notEqual(e, f), notEqual(e, h)); +#elif defined(CORNER_B) + interp_restriction_lv1 = ((e!=f) && (e!=h) && ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) ); +#elif defined(CORNER_D) + interp_restriction_lv1 = ((e!=f) && (e!=h) && ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) && (f!=f4 && f!=i || h!=h5 && h!=i || h!=g || f!=c || eq(b,c1) && eq(d,g0))); +#else + interp_restriction_lv1 = and(and(notEqual(e, f), notEqual(e, h)), + or(or(and(not(eq(f,b)), not(eq(f,c))), + and(not(eq(h,d)), not(eq(h,g)))), + or(and(eq(e,i), or(and(not(eq(f,f4)), not(eq(f,i4))), + and(not(eq(h,h5)), not(eq(h,i5))))), + or(eq(e,g), eq(e,c))))); +#endif + + interp_restriction_lv2_left = and(notEqual(e, g), notEqual(d, g)); + interp_restriction_lv2_up = and(notEqual(e, c), notEqual(b, c)); + interp_restriction_lv3_left = and(eq2(g,g0), not(eq2(d0,g0))); + interp_restriction_lv3_up = and(eq2(c,c1), not(eq2(b1,c1))); + + vec4 fx45 = smoothstep(Co - delta, Co + delta, fx); + vec4 fx30 = smoothstep(Cx - delta, Cx + delta, fx_left); + vec4 fx60 = smoothstep(Cy - delta, Cy + delta, fx_up); + vec4 fx15 = smoothstep(Cz - delta, Cz + delta, fx3_left); + vec4 fx75 = smoothstep(Cw - delta, Cw + delta, fx3_up); + + edr = and(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)), interp_restriction_lv1); + edr_left = and(lessThanEqual((XBR_LV2_COEFFICIENT*df(f,g)), df(h,c)), interp_restriction_lv2_left); + edr_up = and(greaterThanEqual(df(f,g), (XBR_LV2_COEFFICIENT*df(h,c))), interp_restriction_lv2_up); + edr3_left = interp_restriction_lv3_left; + edr3_up = interp_restriction_lv3_up; + + nc45 = and(edr, bvec4(fx45)); + nc30 = and(edr, and(edr_left, bvec4(fx30))); + nc60 = and(edr, and(edr_up, bvec4(fx60))); + nc15 = and(and(edr, edr_left), and(edr3_left, bvec4(fx15))); + nc75 = and(and(edr, edr_up), and(edr3_up, bvec4(fx75))); + + px = lessThanEqual(df(e, f), df(e, h)); + + nc = bvec4(nc75.x || nc15.x || nc30.x || nc60.x || nc45.x, nc75.y || nc15.y || nc30.y || nc60.y || nc45.y, nc75.z || nc15.z || nc30.z || nc60.z || nc45.z, nc75.w || nc15.w || nc30.w || nc60.w || nc45.w); + + vec4 final45 = vec4(nc45) * fx45; + vec4 final30 = vec4(nc30) * fx30; + vec4 final60 = vec4(nc60) * fx60; + vec4 final15 = vec4(nc15) * fx15; + vec4 final75 = vec4(nc75) * fx75; + + vec4 maximo = max(max(max(final15, final75),max(final30, final60)), final45); + + if (nc.x) {pix1 = px.x ? F : H; blend1 = maximo.x;} + else if (nc.y) {pix1 = px.y ? B : F; blend1 = maximo.y;} + else if (nc.z) {pix1 = px.z ? D : B; blend1 = maximo.z;} + else if (nc.w) {pix1 = px.w ? H : D; blend1 = maximo.w;} + + if (nc.w) {pix2 = px.w ? H : D; blend2 = maximo.w;} + else if (nc.z) {pix2 = px.z ? D : B; blend2 = maximo.z;} + else if (nc.y) {pix2 = px.y ? B : F; blend2 = maximo.y;} + else if (nc.x) {pix2 = px.x ? F : H; blend2 = maximo.x;} + + res1 = mix(E, pix1, blend1); + res2 = mix(E, pix2, blend2); + vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2))); + + FragColor = vec4(res, 1.0); } diff --git a/res/shaders/xbr.shader/xbr.vs b/res/shaders/xbr.shader/xbr.vs index 01033d557..d59a970ef 100644 --- a/res/shaders/xbr.shader/xbr.vs +++ b/res/shaders/xbr.shader/xbr.vs @@ -21,57 +21,40 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. */ -// GLSL shader autogenerated by cg2glsl.py. -#if __VERSION__ >= 130 -#define COMPAT_VARYING out -#define COMPAT_ATTRIBUTE in -#define COMPAT_TEXTURE texture -#else -#define COMPAT_VARYING varying -#define COMPAT_ATTRIBUTE attribute -#define COMPAT_TEXTURE texture2D -#endif -#ifdef GL_ES -#define COMPAT_PRECISION mediump -#else -#define COMPAT_PRECISION -#endif -COMPAT_VARYING vec4 _t7; -COMPAT_VARYING vec4 _t6; -COMPAT_VARYING vec4 _t5; -COMPAT_VARYING vec4 _t4; -COMPAT_VARYING vec4 _t3; -COMPAT_VARYING vec4 _t2; -COMPAT_VARYING vec4 _t1; -vec4 _r0007; -COMPAT_ATTRIBUTE vec4 position; -COMPAT_VARYING vec4 TEX0; -COMPAT_VARYING vec4 TEX1; -COMPAT_VARYING vec4 TEX2; -COMPAT_VARYING vec4 TEX3; -COMPAT_VARYING vec4 TEX4; -COMPAT_VARYING vec4 TEX5; -COMPAT_VARYING vec4 TEX6; -COMPAT_VARYING vec4 TEX7; -const COMPAT_PRECISION vec2 TextureSize = vec2(240.0, 160.0); +varying vec2 texCoord; +varying vec4 TEX1; +varying vec4 TEX2; +varying vec4 TEX3; +varying vec4 TEX4; +varying vec4 TEX5; +varying vec4 TEX6; +varying vec4 TEX7; +attribute vec4 position; +/* VERTEX_SHADER */ void main() { - vec2 _ps; - vec2 _texCoord; - _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); - _texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5) + vec2( 1.00000001E-07, 1.00000001E-07); - gl_Position = position; - TEX0.xy = _texCoord; - TEX1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); - TEX2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); - TEX3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); - TEX4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); - TEX5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); - TEX6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); - TEX7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); -} + gl_Position = position; + + vec2 ps = vec2(1.0/240.0, 1.0/160.0); + float dx = ps.x; + float dy = ps.y; + + // A1 B1 C1 + // A0 A B C C4 + // D0 D E F F4 + // G0 G H I I4 + // G5 H5 I5 + + texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5); + TEX1 = texCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1 + TEX2 = texCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C + TEX3 = texCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F + TEX4 = texCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I + TEX5 = texCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5 + TEX6 = texCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0 + TEX7 = texCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4 +} From 6fe43d1d4cfc7c15046e8a7df3354df272e97f4d Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 19:50:31 -0800 Subject: [PATCH 37/68] GBA BIOS: Finish implementing RegisterRamReset --- CHANGES | 1 + README.md | 1 - src/gba/bios.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index a429fcd02..6c323174b 100644 --- a/CHANGES +++ b/CHANGES @@ -63,6 +63,7 @@ Misc: - GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors - Qt: Added button for breaking into the GDB debugger + - GBA BIOS: Finish implementing RegisterRamReset 0.3.2: (2015-12-16) Bugfixes: diff --git a/README.md b/README.md index cb040fde9..dfc0affaf 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,6 @@ Footnotes - OBJ window for modes 3, 4 and 5 ([Bug #5](http://mgba.io/b/5)) - Mosaic for transformed OBJs ([Bug #9](http://mgba.io/b/9)) -- BIOS call RegisterRamReset is partially stubbed out ([Bug #141](http://mgba.io/b/141)) [2] Flash memory size detection does not work in some cases. These can be configured at runtime, but filing a bug is recommended if such a case is encountered. diff --git a/src/gba/bios.c b/src/gba/bios.c index dbb485145..539dcb794 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -71,10 +71,96 @@ static void _RegisterRamReset(struct GBA* gba) { cpu->memory.store32(cpu, BASE_IO | REG_JOY_TRANS, 0, 0); } if (registers & 0x40) { - GBALog(gba, GBA_LOG_STUB, "RegisterRamReset on Audio unimplemented"); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_X, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_X, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_X, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_SOUNDBIAS, 0x200, 0); + memset(gba->audio.ch3.wavedata, 0, sizeof(gba->audio.ch3.wavedata)); } if (registers & 0x80) { - GBALog(gba, GBA_LOG_STUB, "RegisterRamReset on IO unimplemented"); + cpu->memory.store16(cpu, BASE_IO | 0x00, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x04, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x06, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x08, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x0A, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x0C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x0E, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x10, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x12, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x14, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x16, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x18, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x1A, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x1C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x1E, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2PA, 0x100, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2PB, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2PC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2PD, 0x100, 0); + cpu->memory.store32(cpu, BASE_IO | 0x28, 0, 0); + cpu->memory.store32(cpu, BASE_IO | 0x2C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3PA, 0x100, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3PB, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3PC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3PD, 0x100, 0); + cpu->memory.store32(cpu, BASE_IO | 0x38, 0, 0); + cpu->memory.store32(cpu, BASE_IO | 0x3C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x40, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x42, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x44, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x46, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x48, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x4A, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x4C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x50, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x52, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x54, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xB0, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xB2, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xB4, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xB6, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xB8, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xBA, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xBC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xBE, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xC0, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xC2, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xC4, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xC6, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xC8, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xCA, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xCC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xCE, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xD0, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xD2, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xD4, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xD6, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xD8, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xDA, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xDC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0xDE, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x100, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x102, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x104, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x106, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x108, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x10A, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x10C, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x10E, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x200, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x202, 0xFFFF, 0); + cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0); + cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0); } } From 3a134fcda68c4fbe702088640fd8c023567e8679 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 19:52:03 -0800 Subject: [PATCH 38/68] GBA: Allow jumping to OAM and palette RAM --- CHANGES | 1 + src/gba/memory.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGES b/CHANGES index 6c323174b..699fc11d6 100644 --- a/CHANGES +++ b/CHANGES @@ -64,6 +64,7 @@ Misc: - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors - Qt: Added button for breaking into the GDB debugger - GBA BIOS: Finish implementing RegisterRamReset + - GBA: Allow jumping to OAM and palette RAM 0.3.2: (2015-12-16) Bugfixes: diff --git a/src/gba/memory.c b/src/gba/memory.c index 653732154..1d3d87ff4 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -263,10 +263,18 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { cpu->memory.activeRegion = memory->iwram; cpu->memory.activeMask = SIZE_WORKING_IRAM - 1; break; + case REGION_PALETTE_RAM: + cpu->memory.activeRegion = (uint32_t*) gba->video.palette; + cpu->memory.activeMask = SIZE_PALETTE_RAM - 1; + break; case REGION_VRAM: cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram; cpu->memory.activeMask = 0x0000FFFF; break; + case REGION_OAM: + cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw; + cpu->memory.activeMask = SIZE_OAM - 1; + break; case REGION_CART0: case REGION_CART0_EX: case REGION_CART1: From 181174c8107a27009b8ecc86f6018501033df42c Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 20:14:46 -0800 Subject: [PATCH 39/68] Qt: Fix keys being mapped incorrectly when loading configuration file (fixes #212) --- CHANGES | 1 + src/platform/qt/ShortcutController.cpp | 15 ++++++++++----- src/platform/qt/ShortcutController.h | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 699fc11d6..7cbbdf521 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Bugfixes: - Qt: Fix some potential crashes with the gamepad mapping - Debugger: Fix watchpoints in gdb - ARM7: Fix decoding of some ARM ALU instructions with shifters + - Qt: Fix keys being mapped incorrectly when loading configuration file Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper diff --git a/src/platform/qt/ShortcutController.cpp b/src/platform/qt/ShortcutController.cpp index dcbe004fc..8dce4ad8a 100644 --- a/src/platform/qt/ShortcutController.cpp +++ b/src/platform/qt/ShortcutController.cpp @@ -137,10 +137,13 @@ void ShortcutController::addFunctions(QMenu* menu, std::function press, smenu->addFunctions(qMakePair(press, release), shortcut, visibleName, name); endInsertRows(); ShortcutItem* item = &smenu->items().last(); + bool loadedShortcut = false; if (m_config) { - loadShortcuts(item); + loadedShortcut = loadShortcuts(item); + } + if (!loadedShortcut && !m_heldKeys.contains(shortcut)) { + m_heldKeys[shortcut] = item; } - m_heldKeys[shortcut] = item; emit dataChanged(createIndex(smenu->items().count() - 1, 0, item), createIndex(smenu->items().count() - 1, 2, item)); } @@ -387,10 +390,11 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) { return false; } -void ShortcutController::loadShortcuts(ShortcutItem* item) { +bool ShortcutController::loadShortcuts(ShortcutItem* item) { if (item->name().isNull()) { - return; + return false; } + loadGamepadShortcuts(item); QVariant shortcut = m_config->getQtOption(item->name(), KEY_SECTION); if (!shortcut.isNull()) { if (shortcut.toString().endsWith("+")) { @@ -398,8 +402,9 @@ void ShortcutController::loadShortcuts(ShortcutItem* item) { } else { updateKey(item, QKeySequence(shortcut.toString())[0]); } + return true; } - loadGamepadShortcuts(item); + return false; } void ShortcutController::loadGamepadShortcuts(ShortcutItem* item) { diff --git a/src/platform/qt/ShortcutController.h b/src/platform/qt/ShortcutController.h index a486b631c..b128d91e6 100644 --- a/src/platform/qt/ShortcutController.h +++ b/src/platform/qt/ShortcutController.h @@ -128,7 +128,7 @@ protected: private: ShortcutItem* itemAt(const QModelIndex& index); const ShortcutItem* itemAt(const QModelIndex& index) const; - void loadShortcuts(ShortcutItem*); + bool loadShortcuts(ShortcutItem*); void loadGamepadShortcuts(ShortcutItem*); void onSubitems(ShortcutItem*, std::function func); void updateKey(ShortcutItem* item, int keySequence); From e5f2dcb5ab100decb0d12bbb072e0e9a1427d9c1 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 23 Jan 2016 20:52:26 -0800 Subject: [PATCH 40/68] Shaders: Use uniforms for xBR parameters --- res/shaders/xbr.shader/manifest.ini | 28 ++++++++++++++++++++++++++++ res/shaders/xbr.shader/xbr.fs | 8 ++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/res/shaders/xbr.shader/manifest.ini b/res/shaders/xbr.shader/manifest.ini index d25360da3..a60401aa2 100644 --- a/res/shaders/xbr.shader/manifest.ini +++ b/res/shaders/xbr.shader/manifest.ini @@ -8,3 +8,31 @@ passes=1 integerScaling=1 vertexShader=xbr.vs fragmentShader=xbr.fs + +[pass.0.uniform.XBR_Y_WEIGHT] +type=float +default=48 +readableName=Y Weight +min=0 +max=100 + +[pass.0.uniform.XBR_EQ_THRESHOLD] +type=float +readableName=Eq Threshold +default=10.0 +min=0.0 +max=50.0 + +[pass.0.uniform.XBR_EQ_THRESHOLD2] +type=float +readableName=Eq Threshold2 +default=2.0 +min=0.0 +max=4.0 + +[pass.0.uniform.XBR_LV2_COEFFICIENT] +type=float +readableName=Lv2 Coefficient +default=2.0 +min=1.0 +max=3.0 diff --git a/res/shaders/xbr.shader/xbr.fs b/res/shaders/xbr.shader/xbr.fs index dcd779586..69c0faaad 100644 --- a/res/shaders/xbr.shader/xbr.fs +++ b/res/shaders/xbr.shader/xbr.fs @@ -25,10 +25,10 @@ Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. */ -#define XBR_Y_WEIGHT 48.0 -#define XBR_EQ_THRESHOLD 10.0 -#define XBR_EQ_THRESHOLD2 2.0 -#define XBR_LV2_COEFFICIENT 2.0 +uniform float XBR_Y_WEIGHT; +uniform float XBR_EQ_THRESHOLD; +uniform float XBR_EQ_THRESHOLD2; +uniform float XBR_LV2_COEFFICIENT; const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813); const vec4 delta = vec4(0.4, 0.4, 0.4, 0.4); From bee854bb610c2dd6bffd5934783ad2e3c707e3ba Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 01:04:09 -0800 Subject: [PATCH 41/68] Platform: Dirmode is dead --- src/platform/commandline.c | 6 +----- src/platform/commandline.h | 1 - src/platform/qt/GameController.cpp | 16 ++++++---------- src/platform/qt/GameController.h | 3 +-- src/platform/qt/Window.cpp | 2 +- 5 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/platform/commandline.c b/src/platform/commandline.c index dfea7de7a..4e04277fa 100644 --- a/src/platform/commandline.c +++ b/src/platform/commandline.c @@ -36,7 +36,6 @@ static const struct option _options[] = { { "bios", required_argument, 0, 'b' }, { "cheats", required_argument, 0, 'c' }, - { "dirmode", required_argument, 0, 'D' }, { "frameskip", required_argument, 0, 's' }, #ifdef USE_CLI_DEBUGGER { "debug", no_argument, 0, 'd' }, @@ -56,7 +55,7 @@ static bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser) { int ch; char options[64] = - "b:c:Dhl:p:s:v:" + "b:c:hl:p:s:v:" #ifdef USE_CLI_DEBUGGER "d" #endif @@ -86,9 +85,6 @@ bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int arg case 'c': opts->cheatsFile = strdup(optarg); break; - case 'D': - opts->dirmode = true; - break; #ifdef USE_CLI_DEBUGGER case 'd': if (opts->debuggerType != DEBUGGER_NONE) { diff --git a/src/platform/commandline.h b/src/platform/commandline.h index 5f45f444a..737fab8cc 100644 --- a/src/platform/commandline.h +++ b/src/platform/commandline.h @@ -25,7 +25,6 @@ struct GBAArguments { char* fname; char* patch; char* cheatsFile; - bool dirmode; char* movie; enum DebuggerType debuggerType; diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 852bd3ffa..67a63a43d 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -281,26 +281,22 @@ void GameController::setDebugger(ARMDebugger* debugger) { } #endif -void GameController::loadGame(const QString& path, bool dirmode) { +void GameController::loadGame(const QString& path) { closeGame(); - if (!dirmode) { - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - postLog(GBA_LOG_ERROR, tr("Failed to open game file: %1").arg(path)); - return; - } - file.close(); + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { + postLog(GBA_LOG_ERROR, tr("Failed to open game file: %1").arg(path)); + return; } + file.close(); m_fname = path; - m_dirmode = dirmode; openGame(); } void GameController::bootBIOS() { closeGame(); m_fname = QString(); - m_dirmode = false; openGame(true); } diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 4f118df27..adda42243 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -97,7 +97,7 @@ signals: void postLog(int level, const QString& log); public slots: - void loadGame(const QString& path, bool dirmode = false); + void loadGame(const QString& path); void loadBIOS(const QString& path); void yankPak(); void replaceGame(const QString& path); @@ -180,7 +180,6 @@ private: int m_logLevels; bool m_gameOpen; - bool m_dirmode; QString m_fname; QString m_bios; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 3b11f1f12..d5d8f30dd 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -180,7 +180,7 @@ void Window::argumentsPassed(GBAArguments* args) { } if (args->fname) { - m_controller->loadGame(args->fname, args->dirmode); + m_controller->loadGame(args->fname); } } From 15dadb8387a12468e784e4fd2ebac899da642291 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 14:23:59 -0800 Subject: [PATCH 42/68] GBA Cheats: Fix cheats setting the Action Replay version --- CHANGES | 1 + src/gba/cheats/gameshark.c | 6 +++++- src/gba/cheats/parv3.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 7cbbdf521..3b21347f0 100644 --- a/CHANGES +++ b/CHANGES @@ -35,6 +35,7 @@ Bugfixes: - Debugger: Fix watchpoints in gdb - ARM7: Fix decoding of some ARM ALU instructions with shifters - Qt: Fix keys being mapped incorrectly when loading configuration file + - GBA Cheats: Fix cheats setting the Action Replay version Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper diff --git a/src/gba/cheats/gameshark.c b/src/gba/cheats/gameshark.c index 996de638d..3f54df670 100644 --- a/src/gba/cheats/gameshark.c +++ b/src/gba/cheats/gameshark.c @@ -75,12 +75,14 @@ void GBACheatReseedGameShark(uint32_t* seeds, uint16_t params, const uint8_t* t1 } void GBACheatSetGameSharkVersion(struct GBACheatSet* cheats, int version) { - cheats->gsaVersion = 1; + cheats->gsaVersion = version; switch (version) { case 1: + case 2: memcpy(cheats->gsaSeeds, GBACheatGameSharkSeeds, 4 * sizeof(uint32_t)); break; case 3: + case 4: memcpy(cheats->gsaSeeds, GBACheatProActionReplaySeeds, 4 * sizeof(uint32_t)); break; } @@ -198,9 +200,11 @@ bool GBACheatAddGameShark(struct GBACheatSet* set, uint32_t op1, uint32_t op2) { switch (set->gsaVersion) { case 0: case 3: + case 4: GBACheatSetGameSharkVersion(set, 1); // Fall through case 1: + case 2: GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds); return GBACheatAddGameSharkRaw(set, o1, o2); } diff --git a/src/gba/cheats/parv3.c b/src/gba/cheats/parv3.c index c5e01b66d..b355a18b0 100644 --- a/src/gba/cheats/parv3.c +++ b/src/gba/cheats/parv3.c @@ -298,9 +298,11 @@ bool GBACheatAddProActionReplay(struct GBACheatSet* set, uint32_t op1, uint32_t switch (set->gsaVersion) { case 0: case 1: + case 2: GBACheatSetGameSharkVersion(set, 3); // Fall through case 3: + case 4: GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds); return GBACheatAddProActionReplayRaw(set, o1, o2); } From a53c3e0628461b179ed2b605339c314617d1aa66 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 14:24:53 -0800 Subject: [PATCH 43/68] OpenEmu: Cheat support --- src/platform/openemu/Info.plist.in | 2 ++ src/platform/openemu/mGBAGameCore.m | 47 ++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/platform/openemu/Info.plist.in b/src/platform/openemu/Info.plist.in index 9ab3b28f5..0642d81f1 100644 --- a/src/platform/openemu/Info.plist.in +++ b/src/platform/openemu/Info.plist.in @@ -32,6 +32,8 @@ 0 OEGameCoreSupportsRewinding + OEGameCoreSupportsCheatCode + OEGameCorePlayerCount diff --git a/src/platform/openemu/mGBAGameCore.m b/src/platform/openemu/mGBAGameCore.m index 5f220fb95..a5749d6d8 100644 --- a/src/platform/openemu/mGBAGameCore.m +++ b/src/platform/openemu/mGBAGameCore.m @@ -27,6 +27,7 @@ #include "util/common.h" #include "gba/cheats.h" +#include "gba/cheats/gameshark.h" #include "gba/renderers/video-software.h" #include "gba/serialize.h" #include "gba/context/context.h" @@ -45,7 +46,7 @@ struct GBAContext context; struct GBAVideoSoftwareRenderer renderer; struct GBACheatDevice cheats; - struct GBACheatSet cheatSet; + NSMutableDictionary *cheatSets; uint16_t keys; } @end @@ -70,8 +71,7 @@ GBAAudioResizeBuffer(&context.gba->audio, SAMPLES); GBACheatDeviceCreate(&cheats); GBACheatAttachDevice(context.gba, &cheats); - GBACheatSetInit(&cheatSet, "openemu"); - GBACheatAddSet(&cheats, &cheatSet); + cheatSets = [[NSMutableDictionary alloc] init]; keys = 0; } @@ -81,9 +81,18 @@ - (void)dealloc { GBAContextDeinit(&context); - GBACheatRemoveSet(&cheats, &cheatSet); + [cheatSets enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + UNUSED(key); + UNUSED(stop); + GBACheatRemoveSet(&cheats, [obj pointerValue]); + }]; GBACheatDeviceDestroy(&cheats); - GBACheatSetDeinit(&cheatSet); + [cheatSets enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + UNUSED(key); + UNUSED(stop); + GBACheatSetDeinit([obj pointerValue]); + }]; + [cheatSets release]; free(renderer.outputBuffer); [super dealloc]; @@ -275,5 +284,33 @@ const int GBAMap[] = { keys &= ~(1 << GBAMap[button]); } +#pragma mark - Cheats + +- (void)setCheat:(NSString *)code setType:(NSString *)type setEnabled:(BOOL)enabled +{ + code = [code stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + code = [code stringByReplacingOccurrencesOfString:@" " withString:@""]; + + NSString *codeId = [code stringByAppendingFormat:@"/%@", type]; + struct GBACheatSet* cheatSet = [[cheatSets objectForKey:codeId] pointerValue]; + if (cheatSet) { + cheatSet->enabled = enabled; + return; + } + cheatSet = malloc(sizeof(*cheatSet)); + GBACheatSetInit(cheatSet, [codeId UTF8String]); + if ([type isEqual:@"GameShark"]) { + GBACheatSetGameSharkVersion(cheatSet, 1); + } else if ([type isEqual:@"Action Replay"]) { + GBACheatSetGameSharkVersion(cheatSet, 3); + } + NSArray *codeSet = [code componentsSeparatedByString:@"+"]; + for (id c in codeSet) { + GBACheatAddLine(cheatSet, [c UTF8String]); + } + cheatSet->enabled = enabled; + [cheatSets setObject:[NSValue valueWithPointer:cheatSet] forKey:codeId]; + GBACheatAddSet(&cheats, cheatSet); +} @end From e436f2a7276d162dd2cd9b2f4686108820ae77b7 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 17:48:44 -0800 Subject: [PATCH 44/68] GBA Cheats: Add GBACheatDeviceClear --- src/gba/cheats.c | 7 ++++++- src/gba/cheats.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gba/cheats.c b/src/gba/cheats.c index 0bbd2b06b..a9702bd4e 100644 --- a/src/gba/cheats.c +++ b/src/gba/cheats.c @@ -110,13 +110,18 @@ void GBACheatDeviceCreate(struct GBACheatDevice* device) { } void GBACheatDeviceDestroy(struct GBACheatDevice* device) { + GBACheatDeviceClear(device); + GBACheatSetsDeinit(&device->cheats); +} + +void GBACheatDeviceClear(struct GBACheatDevice* device) { size_t i; for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) { struct GBACheatSet* set = *GBACheatSetsGetPointer(&device->cheats, i); GBACheatSetDeinit(set); free(set); } - GBACheatSetsDeinit(&device->cheats); + GBACheatSetsClear(&device->cheats); } void GBACheatSetInit(struct GBACheatSet* set, const char* name) { diff --git a/src/gba/cheats.h b/src/gba/cheats.h index 73b08940a..2bf992ff2 100644 --- a/src/gba/cheats.h +++ b/src/gba/cheats.h @@ -192,6 +192,7 @@ struct VFile; void GBACheatDeviceCreate(struct GBACheatDevice*); void GBACheatDeviceDestroy(struct GBACheatDevice*); +void GBACheatDeviceClear(struct GBACheatDevice*); void GBACheatSetInit(struct GBACheatSet*, const char* name); void GBACheatSetDeinit(struct GBACheatSet*); From 26e9e8d63ffab9b6d2cc3c83d8ed1c758eba6496 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 17:50:18 -0800 Subject: [PATCH 45/68] GBA Cheats: Remove trailing newline --- src/gba/cheats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gba/cheats.c b/src/gba/cheats.c index a9702bd4e..097679bc5 100644 --- a/src/gba/cheats.c +++ b/src/gba/cheats.c @@ -265,6 +265,7 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) { do { ++i; } while (isspace((int) cheat[i])); + cheat[strlen(cheat) - 1] = '\0'; // Remove trailing newline newSet = malloc(sizeof(*set)); GBACheatSetInit(newSet, &cheat[i]); newSet->enabled = !nextDisabled; From 0501944b5abccaceb9046091bf21f39ec7696d22 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 17:59:45 -0800 Subject: [PATCH 46/68] GBA: Savestates can store currently used cheats --- src/gba/serialize.c | 32 ++++++++++++++++++++++++++++++++ src/gba/serialize.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 8d756bd7f..1e6c48061 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -6,6 +6,7 @@ #include "serialize.h" #include "gba/audio.h" +#include "gba/cheats.h" #include "gba/io.h" #include "gba/rr/rr.h" #include "gba/supervisor/thread.h" @@ -426,6 +427,20 @@ bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags) { } svf->close(svf); } + struct VFile* cheatVf = 0; + if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) { + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + cheatVf = VFileMemChunk(0, 0); + if (cheatVf) { + GBACheatSaveFile(device, cheatVf); + struct GBAExtdataItem item = { + .size = cheatVf->size(cheatVf), + .data = cheatVf->map(cheatVf, cheatVf->size(cheatVf), MAP_READ), + .clean = 0 + }; + GBAExtdataPut(&extdata, EXTDATA_CHEATS, &item); + } + }; #ifdef USE_PNG if (!(flags & SAVESTATE_SCREENSHOT)) { #else @@ -435,6 +450,9 @@ bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags) { struct GBASerializedState* state = vf->map(vf, sizeof(struct GBASerializedState), MAP_WRITE); if (!state) { GBAExtdataDeinit(&extdata); + if (cheatVf) { + cheatVf->close(cheatVf); + } return false; } GBASerialize(gba, state); @@ -442,6 +460,9 @@ bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags) { vf->seek(vf, sizeof(struct GBASerializedState), SEEK_SET); GBAExtdataSerialize(&extdata, vf); GBAExtdataDeinit(&extdata); + if (cheatVf) { + cheatVf->close(cheatVf); + } return true; #ifdef USE_PNG } @@ -502,6 +523,17 @@ bool GBALoadStateNamed(struct GBA* gba, struct VFile* vf, int flags) { svf->close(svf); } } + if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE] && GBAExtdataGet(&extdata, EXTDATA_CHEATS, &item)) { + if (item.size) { + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + struct VFile* svf = VFileFromMemory(item.data, item.size); + if (svf) { + GBACheatDeviceClear(device); + GBACheatParseFile(device, svf); + svf->close(svf); + } + } + } GBAExtdataDeinit(&extdata); return success; } diff --git a/src/gba/serialize.h b/src/gba/serialize.h index a1df2330b..97d4a6ee8 100644 --- a/src/gba/serialize.h +++ b/src/gba/serialize.h @@ -339,11 +339,13 @@ enum GBAExtdataTag { EXTDATA_NONE = 0, EXTDATA_SCREENSHOT = 1, EXTDATA_SAVEDATA = 2, + EXTDATA_CHEATS = 3, EXTDATA_MAX }; #define SAVESTATE_SCREENSHOT 1 #define SAVESTATE_SAVEDATA 2 +#define SAVESTATE_CHEATS 4 struct GBAExtdataItem { int32_t size; From 6d8a34a6dcb5c819a978933bf47f3396ab6a7d3a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 24 Jan 2016 18:25:07 -0800 Subject: [PATCH 47/68] Qt: Unify state saving/loading flags --- src/platform/qt/CheatsView.cpp | 1 + src/platform/qt/GameController.cpp | 10 ++++++---- src/platform/qt/GameController.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/CheatsView.cpp b/src/platform/qt/CheatsView.cpp index 357a0c788..4ba25aef7 100644 --- a/src/platform/qt/CheatsView.cpp +++ b/src/platform/qt/CheatsView.cpp @@ -31,6 +31,7 @@ CheatsView::CheatsView(GameController* controller, QWidget* parent) connect(m_ui.addSet, SIGNAL(clicked()), this, SLOT(addSet())); connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet())); connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated())); + connect(controller, SIGNAL(stateLoaded(GBAThread*)), &m_model, SLOT(invalidated())); connect(m_ui.add, &QPushButton::clicked, [this]() { enterCheat(GBACheatAddLine); diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 67a63a43d..d2d900d0d 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -58,6 +58,8 @@ GameController::GameController(QObject* parent) , m_stateSlot(1) , m_backupLoadState(nullptr) , m_backupSaveState(nullptr) + , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS) + , m_loadStateFlags(SAVESTATE_SCREENSHOT) { m_renderer = new GBAVideoSoftwareRenderer; GBAVideoSoftwareRendererCreate(m_renderer); @@ -112,7 +114,7 @@ GameController::GameController(QObject* parent) context->gba->video.renderer->disableOBJ = !controller->m_videoLayers[4]; controller->m_fpsTarget = context->fpsTarget; - if (context->dirs.state && GBALoadState(context, context->dirs.state, 0, SAVESTATE_SCREENSHOT)) { + if (context->dirs.state && GBALoadState(context, context->dirs.state, 0, controller->m_loadStateFlags)) { VFile* vf = GBAGetState(context->gba, context->dirs.state, 0, true); if (vf) { vf->truncate(vf, 0); @@ -141,7 +143,7 @@ GameController::GameController(QObject* parent) return false; } GameController* controller = static_cast(context->userData); - if (!GBASaveState(context, context->dirs.state, 0, true)) { + if (!GBASaveState(context, context->dirs.state, 0, controller->m_saveStateFlags)) { return false; } QMetaObject::invokeMethod(controller, "closeGame"); @@ -710,7 +712,7 @@ void GameController::loadState(int slot) { controller->m_backupLoadState = new GBASerializedState; } GBASerialize(context->gba, controller->m_backupLoadState); - if (GBALoadState(context, context->dirs.state, controller->m_stateSlot, SAVESTATE_SCREENSHOT)) { + if (GBALoadState(context, context->dirs.state, controller->m_stateSlot, controller->m_loadStateFlags)) { controller->frameAvailable(controller->m_drawContext); controller->stateLoaded(context); } @@ -733,7 +735,7 @@ void GameController::saveState(int slot) { vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); vf->close(vf); } - GBASaveState(context, context->dirs.state, controller->m_stateSlot, SAVESTATE_SCREENSHOT | EXTDATA_SAVEDATA); + GBASaveState(context, context->dirs.state, controller->m_stateSlot, controller->m_saveStateFlags); }); } diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index adda42243..0d757bce1 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -209,6 +209,8 @@ private: int m_stateSlot; GBASerializedState* m_backupLoadState; QByteArray m_backupSaveState; + int m_saveStateFlags; + int m_loadStateFlags; InputController* m_inputController; MultiplayerController* m_multiplayer; From 4f1788b2e05744fbb6e5ee24af3d02e2ba2304ba Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 25 Jan 2016 20:11:30 -0800 Subject: [PATCH 48/68] Qt: Add ability to customize savestate data, add rewind duration box --- CHANGES | 2 + src/platform/qt/GameController.cpp | 8 + src/platform/qt/GameController.h | 2 + src/platform/qt/SettingsView.cpp | 138 +++++++---- src/platform/qt/SettingsView.h | 2 + src/platform/qt/SettingsView.ui | 361 +++++++++++++++++++---------- src/platform/qt/Window.cpp | 23 ++ 7 files changed, 374 insertions(+), 162 deletions(-) diff --git a/CHANGES b/CHANGES index 3b21347f0..0d17fab74 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Features: - Added a setting for pausing when the emulator is not in focus - Customizable paths for save games, save states, screenshots and patches - Controller hotplugging + - Ability to store save games and active cheats within savestates Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline @@ -67,6 +68,7 @@ Misc: - Qt: Added button for breaking into the GDB debugger - GBA BIOS: Finish implementing RegisterRamReset - GBA: Allow jumping to OAM and palette RAM + - Qt: Add box for showing duration of rewind 0.3.2: (2015-12-16) Bugfixes: diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index d2d900d0d..7722b7715 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -907,6 +907,14 @@ void GameController::reloadAudioDriver() { } } +void GameController::setSaveStateExtdata(int flags) { + m_saveStateFlags = flags; +} + +void GameController::setLoadStateExtdata(int flags) { + m_loadStateFlags = flags; +} + void GameController::setLuminanceValue(uint8_t value) { m_luxValue = value; value = std::max(value - 0x16, 0); diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 0d757bce1..a7a3d89ae 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -138,6 +138,8 @@ public slots: void setAVStream(GBAAVStream*); void clearAVStream(); void reloadAudioDriver(); + void setSaveStateExtdata(int flags); + void setLoadStateExtdata(int flags); #ifdef USE_PNG void screenshot(); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 810079459..48ed5e4e8 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -13,6 +13,10 @@ #include "InputController.h" #include "ShortcutView.h" +extern "C" { +#include "gba/serialize.h" +} + using namespace QGBA; SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent) @@ -21,29 +25,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC { m_ui.setupUi(this); - loadSetting("bios", m_ui.bios); - loadSetting("useBios", m_ui.useBios); - loadSetting("skipBios", m_ui.skipBios); - loadSetting("audioBuffers", m_ui.audioBufferSize); - loadSetting("sampleRate", m_ui.sampleRate); - loadSetting("videoSync", m_ui.videoSync); - loadSetting("audioSync", m_ui.audioSync); - loadSetting("frameskip", m_ui.frameskip); - loadSetting("fpsTarget", m_ui.fpsTarget); - loadSetting("lockAspectRatio", m_ui.lockAspectRatio); - loadSetting("volume", m_ui.volume); - loadSetting("mute", m_ui.mute); - loadSetting("rewindEnable", m_ui.rewind); - loadSetting("rewindBufferInterval", m_ui.rewindInterval); - loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); - loadSetting("resampleVideo", m_ui.resampleVideo); - loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections); - loadSetting("suspendScreensaver", m_ui.suspendScreensaver); - loadSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); - loadSetting("savegamePath", m_ui.savegamePath); - loadSetting("savestatePath", m_ui.savestatePath); - loadSetting("screenshotPath", m_ui.screenshotPath); - loadSetting("patchPath", m_ui.patchPath); + reloadConfig(); if (m_ui.savegamePath->text().isEmpty()) { m_ui.savegameSameDir->setChecked(true); @@ -109,28 +91,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC } }); - double fastForwardRatio = loadSetting("fastForwardRatio").toDouble(); - if (fastForwardRatio <= 0) { - m_ui.fastForwardUnbounded->setChecked(true); - m_ui.fastForwardRatio->setEnabled(false); - } else { - m_ui.fastForwardUnbounded->setChecked(false); - m_ui.fastForwardRatio->setEnabled(true); - m_ui.fastForwardRatio->setValue(fastForwardRatio); - } - connect(m_ui.fastForwardUnbounded, &QAbstractButton::toggled, [this](bool checked) { - m_ui.fastForwardRatio->setEnabled(!checked); - }); - - QString idleOptimization = loadSetting("idleOptimization"); - if (idleOptimization == "ignore") { - m_ui.idleOptimization->setCurrentIndex(0); - } else if (idleOptimization == "remove") { - m_ui.idleOptimization->setCurrentIndex(1); - } else if (idleOptimization == "detect") { - m_ui.idleOptimization->setCurrentIndex(2); - } - + // TODO: Move to reloadConfig() QVariant audioDriver = m_controller->getQtOption("audioDriver"); #ifdef BUILD_QT_MULTIMEDIA m_ui.audioDriver->addItem(tr("Qt Multimedia"), static_cast(AudioProcessor::Driver::QT_MULTIMEDIA)); @@ -146,6 +107,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC } #endif + // TODO: Move to reloadConfig() QVariant displayDriver = m_controller->getQtOption("displayDriver"); m_ui.displayDriver->addItem(tr("Software (Qt)"), static_cast(Display::Driver::QT)); if (!displayDriver.isNull() && displayDriver.toInt() == static_cast(Display::Driver::QT)) { @@ -195,6 +157,14 @@ void SettingsView::selectBios() { } } +void SettingsView::recalculateRewind() { + int interval = m_ui.rewindInterval->value(); + int capacity = m_ui.rewindCapacity->value(); + double duration = m_ui.fpsTarget->value(); + m_ui.rewindDuration->setValue(interval * capacity / duration); + +} + void SettingsView::updateConfig() { saveSetting("bios", m_ui.bios); saveSetting("useBios", m_ui.useBios); @@ -238,6 +208,18 @@ void SettingsView::updateConfig() { break; } + int loadState = 0; + loadState |= m_ui.loadStateScreenshot->isChecked() ? SAVESTATE_SCREENSHOT : 0; + loadState |= m_ui.loadStateSave->isChecked() ? SAVESTATE_SAVEDATA : 0; + loadState |= m_ui.loadStateCheats->isChecked() ? SAVESTATE_CHEATS : 0; + saveSetting("loadStateExtdata", loadState); + + int saveState = 0; + saveState |= m_ui.saveStateScreenshot->isChecked() ? SAVESTATE_SCREENSHOT : 0; + saveState |= m_ui.saveStateSave->isChecked() ? SAVESTATE_SAVEDATA : 0; + saveState |= m_ui.saveStateCheats->isChecked() ? SAVESTATE_CHEATS : 0; + saveSetting("saveStateExtdata", saveState); + QVariant audioDriver = m_ui.audioDriver->itemData(m_ui.audioDriver->currentIndex()); if (audioDriver != m_controller->getQtOption("audioDriver")) { m_controller->setQtOption("audioDriver", audioDriver); @@ -258,6 +240,72 @@ void SettingsView::updateConfig() { emit biosLoaded(m_ui.bios->text()); } +void SettingsView::reloadConfig() { + loadSetting("bios", m_ui.bios); + loadSetting("useBios", m_ui.useBios); + loadSetting("skipBios", m_ui.skipBios); + loadSetting("audioBuffers", m_ui.audioBufferSize); + loadSetting("sampleRate", m_ui.sampleRate); + loadSetting("videoSync", m_ui.videoSync); + loadSetting("audioSync", m_ui.audioSync); + loadSetting("frameskip", m_ui.frameskip); + loadSetting("fpsTarget", m_ui.fpsTarget); + loadSetting("lockAspectRatio", m_ui.lockAspectRatio); + loadSetting("volume", m_ui.volume); + loadSetting("mute", m_ui.mute); + loadSetting("rewindEnable", m_ui.rewind); + loadSetting("rewindBufferInterval", m_ui.rewindInterval); + loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); + loadSetting("resampleVideo", m_ui.resampleVideo); + loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections); + loadSetting("suspendScreensaver", m_ui.suspendScreensaver); + loadSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost); + loadSetting("savegamePath", m_ui.savegamePath); + loadSetting("savestatePath", m_ui.savestatePath); + loadSetting("screenshotPath", m_ui.screenshotPath); + loadSetting("patchPath", m_ui.patchPath); + + double fastForwardRatio = loadSetting("fastForwardRatio").toDouble(); + if (fastForwardRatio <= 0) { + m_ui.fastForwardUnbounded->setChecked(true); + m_ui.fastForwardRatio->setEnabled(false); + } else { + m_ui.fastForwardUnbounded->setChecked(false); + m_ui.fastForwardRatio->setEnabled(true); + m_ui.fastForwardRatio->setValue(fastForwardRatio); + } + + connect(m_ui.rewindInterval, SIGNAL(valueChanged(int)), this, SLOT(recalculateRewind())); + connect(m_ui.rewindCapacity, SIGNAL(valueChanged(int)), this, SLOT(recalculateRewind())); + connect(m_ui.fpsTarget, SIGNAL(valueChanged(double)), this, SLOT(recalculateRewind())); + + QString idleOptimization = loadSetting("idleOptimization"); + if (idleOptimization == "ignore") { + m_ui.idleOptimization->setCurrentIndex(0); + } else if (idleOptimization == "remove") { + m_ui.idleOptimization->setCurrentIndex(1); + } else if (idleOptimization == "detect") { + m_ui.idleOptimization->setCurrentIndex(2); + } + + bool ok; + int loadState = loadSetting("loadStateExtdata").toInt(&ok); + if (!ok) { + loadState = SAVESTATE_SCREENSHOT; + } + m_ui.loadStateScreenshot->setChecked(loadState & SAVESTATE_SCREENSHOT); + m_ui.loadStateSave->setChecked(loadState & SAVESTATE_SAVEDATA); + m_ui.loadStateCheats->setChecked(loadState & SAVESTATE_CHEATS); + + int saveState = loadSetting("saveStateExtdata").toInt(&ok); + if (!ok) { + saveState = SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS; + } + m_ui.saveStateScreenshot->setChecked(saveState & SAVESTATE_SCREENSHOT); + m_ui.saveStateSave->setChecked(saveState & SAVESTATE_SAVEDATA); + m_ui.saveStateCheats->setChecked(saveState & SAVESTATE_CHEATS); +} + void SettingsView::saveSetting(const char* key, const QAbstractButton* field) { m_controller->setOption(key, field->isChecked()); m_controller->updateOption(key); diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 4ccdabf0e..77d672bdf 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -30,7 +30,9 @@ signals: private slots: void selectBios(); + void recalculateRewind(); void updateConfig(); + void reloadConfig(); private: Ui::SettingsView m_ui; diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 6a2cca0bb..22a94947f 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -6,8 +6,8 @@ 0 0 - 568 - 451 + 544 + 425 @@ -23,10 +23,56 @@ QLayout::SetFixedSize + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + 0 + 0 + + + + + 140 + 16777215 + + + + 0 + + + + Audio/Video + + + + + Emulation + + + + + Savestates + + + + + Paths + + + + - 0 + 2 @@ -374,77 +420,35 @@ - Use BIOS file + Use BIOS file if found true + + + + Skip BIOS intro + + + + + + + Qt::Horizontal + + + - - - Create rewind state: - - - - - - - Enable rewind - - - - - - - - - Every - - - - - - - - - - frames - - - - - - - - - Rewind history: - - - - - - - - - - - - states - - - - - - Fast forward speed - + false @@ -466,7 +470,7 @@ - + Unbounded @@ -476,14 +480,21 @@ - + + + + Qt::Horizontal + + + + Allow opposing input directions - + Suspend screensaver @@ -493,14 +504,21 @@ - + + + + Pause when inactive + + + + Idle loops - + @@ -519,41 +537,172 @@ - - + + + + + + QFormLayout::FieldsStayAtSizeHint + + + - Skip BIOS intro + Save extra data - - + + + + Screenshot + + + true + + + + + + + Save data + + + true + + + + + + + Cheat codes + + + true + + + + + Qt::Horizontal - + + + + Load extra data + + + + + + + Screenshot + + + true + + + + + + + Save data + + + + + + + Cheat codes + + + + Qt::Horizontal - - - - Qt::Horizontal + + + + Enable rewind - - + + - Pause when inactive + Create rewind state: + + + + + + Every + + + + + + + + + + frames + + + + + + + + + Rewind history: + + + + + + + + + + + + states + + + + + + + + + + + false + + + 999.990000000000009 + + + + + + + seconds + + + + + @@ -750,44 +899,6 @@ - - - - - 0 - 0 - - - - - 140 - 16777215 - - - - - Audio/Video - - - - - Emulation - - - - - Paths - - - - - - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -904,5 +1015,21 @@ + + fastForwardUnbounded + toggled(bool) + fastForwardRatio + setDisabled(bool) + + + 338 + 163 + + + 327 + 135 + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index d5d8f30dd..2e6b70da6 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -241,6 +241,19 @@ void Window::reloadConfig() { m_log.setLevels(opts->logLevel); + QString saveStateExtdata = m_config->getOption("saveStateExtdata"); + bool ok; + int flags = saveStateExtdata.toInt(&ok); + if (ok) { + m_controller->setSaveStateExtdata(flags); + } + + QString loadStateExtdata = m_config->getOption("loadStateExtdata"); + flags = loadStateExtdata.toInt(&ok); + if (ok) { + m_controller->setLoadStateExtdata(flags); + } + m_controller->setOptions(opts); m_display->lockAspectRatio(opts->lockAspectRatio); m_display->filter(opts->resampleVideo); @@ -1239,6 +1252,16 @@ void Window::setupMenu(QMenuBar* menubar) { m_inputController.setAllowOpposing(value.toBool()); }, this); + ConfigOption* saveStateExtdata = m_config->addOption("saveStateExtdata"); + saveStateExtdata->connect([this](const QVariant& value) { + m_controller->setSaveStateExtdata(value.toInt()); + }, this); + + ConfigOption* loadStateExtdata = m_config->addOption("loadStateExtdata"); + loadStateExtdata->connect([this](const QVariant& value) { + m_controller->setLoadStateExtdata(value.toInt()); + }, this); + QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu); connect(exitFullScreen, SIGNAL(triggered()), this, SLOT(exitFullScreen())); exitFullScreen->setShortcut(QKeySequence("Esc")); From 388582776e5b7b01ed7ceeb4bcb668b1b2a2b367 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 25 Jan 2016 20:11:55 -0800 Subject: [PATCH 49/68] Qt: Allow loading of ZIPs when using minizip --- src/platform/qt/Window.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 2e6b70da6..210c09da7 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -273,7 +273,7 @@ void Window::saveConfig() { void Window::selectROM() { QStringList formats{ "*.gba", -#ifdef USE_LIBZIP +#if defined(USE_LIBZIP) || defined(USE_ZLIB) "*.zip", #endif #ifdef USE_LZMA @@ -293,7 +293,7 @@ void Window::selectROM() { void Window::replaceROM() { QStringList formats{ "*.gba", -#ifdef USE_LIBZIP +#if defined(USE_LIBZIP) || defined(USE_ZLIB) "*.zip", #endif #ifdef USE_LZMA From b9b650ead2a742c8461804a96a71bd78d3b81e9d Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 26 Jan 2016 23:19:25 -0800 Subject: [PATCH 50/68] Qt: Fix default settings page --- src/platform/qt/SettingsView.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 22a94947f..0b1b45333 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -72,7 +72,7 @@ - 2 + 0 From 7436a5afef25fcb9160aa1884cc31503bc739f2b Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 26 Jan 2016 23:28:34 -0800 Subject: [PATCH 51/68] OpenGL: Simplify desaturation by using mix --- src/platform/opengl/gles2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index cff5dab27..e19f8b44a 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -50,7 +50,7 @@ static const char* const _fragmentShader = " vec4 color = texture2D(tex, texCoord);\n" " color.a = 1.;\n" " float average = dot(color.rgb, vec3(1.)) / 3.;\n" - " color.rgb = vec3(average) * desaturation + color.rgb * (vec3(1.) - desaturation);\n" + " color.rgb = mix(color.rgb, vec3(average), desaturation);\n" " color.rgb = scale * pow(color.rgb, vec3(gamma, gamma, gamma)) + bias;\n" " gl_FragColor = color;\n" "}"; From f1fba591524169276a95043354601b969d4deeb4 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 28 Jan 2016 22:52:45 -0800 Subject: [PATCH 52/68] GBA Context: Add additional constraints on MINIMAL_CORE==2 --- src/gba/context/context.c | 10 ++++++++++ src/gba/context/context.h | 2 ++ src/gba/context/directories.c | 2 ++ src/gba/context/directories.h | 2 ++ src/gba/supervisor/thread.h | 2 ++ 5 files changed, 18 insertions(+) diff --git a/src/gba/context/context.c b/src/gba/context/context.c index 21e9be4ae..d9e33730a 100644 --- a/src/gba/context/context.c +++ b/src/gba/context/context.c @@ -21,7 +21,9 @@ bool GBAContextInit(struct GBAContext* context, const char* port) { context->fname = 0; context->save = 0; context->renderer = 0; +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 GBADirectorySetInit(&context->dirs); +#endif memset(context->components, 0, sizeof(context->components)); if (!context->gba || !context->cpu) { @@ -79,11 +81,17 @@ void GBAContextDeinit(struct GBAContext* context) { mappedMemoryFree(context->gba, 0); mappedMemoryFree(context->cpu, 0); GBAConfigDeinit(&context->config); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 GBADirectorySetDeinit(&context->dirs); +#endif } bool GBAContextLoadROM(struct GBAContext* context, const char* path, bool autoloadSave) { +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 context->rom = GBADirectorySetOpenPath(&context->dirs, path, GBAIsROM); +#else + context->rom = VFileOpen(path, O_RDONLY); +#endif if (!context->rom) { return false; } @@ -106,7 +114,9 @@ bool GBAContextLoadROM(struct GBAContext* context, const char* path, bool autolo void GBAContextUnloadROM(struct GBAContext* context) { GBAUnloadROM(context->gba); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 GBADirectorySetDetachBase(&context->dirs); +#endif if (context->rom) { context->rom->close(context->rom); context->rom = 0; diff --git a/src/gba/context/context.h b/src/gba/context/context.h index d71385074..36168371a 100644 --- a/src/gba/context/context.h +++ b/src/gba/context/context.h @@ -21,7 +21,9 @@ struct GBAContext { const char* fname; struct VFile* save; struct VFile* bios; +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct GBADirectorySet dirs; +#endif struct ARMComponent* components[GBA_COMPONENT_MAX]; struct GBAConfig config; struct GBAOptions opts; diff --git a/src/gba/context/directories.c b/src/gba/context/directories.c index 23648567c..68f59dc01 100644 --- a/src/gba/context/directories.c +++ b/src/gba/context/directories.c @@ -8,6 +8,7 @@ #include "gba/context/config.h" #include "util/vfs.h" +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 void GBADirectorySetInit(struct GBADirectorySet* dirs) { dirs->base = 0; dirs->archive = 0; @@ -142,3 +143,4 @@ void GBADirectorySetMapOptions(struct GBADirectorySet* dirs, const struct GBAOpt } } } +#endif diff --git a/src/gba/context/directories.h b/src/gba/context/directories.h index 7292c59ae..e0a74c53e 100644 --- a/src/gba/context/directories.h +++ b/src/gba/context/directories.h @@ -8,6 +8,7 @@ #include "util/common.h" +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct VDir; struct GBADirectorySet { @@ -29,5 +30,6 @@ struct VFile* GBADirectorySetOpenPath(struct GBADirectorySet* dirs, const char* struct GBAOptions; void GBADirectorySetMapOptions(struct GBADirectorySet* dirs, const struct GBAOptions* opts); +#endif #endif diff --git a/src/gba/supervisor/thread.h b/src/gba/supervisor/thread.h index 2a70d233c..9eee6a659 100644 --- a/src/gba/supervisor/thread.h +++ b/src/gba/supervisor/thread.h @@ -48,7 +48,9 @@ struct GBAThread { struct GBAVideoRenderer* renderer; struct GBASIODriverSet sioDrivers; struct ARMDebugger* debugger; +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct GBADirectorySet dirs; +#endif struct VFile* rom; struct VFile* save; struct VFile* bios; From 6ee60dd79b6106385c5b2b26cfab00257fccf19a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 30 Jan 2016 14:02:35 -0800 Subject: [PATCH 53/68] GUI: UI refinements, fixes --- src/platform/3ds/gui-font.c | 11 +++++++++ src/platform/psp2/gui-font.c | 19 +++++++++++---- src/platform/wii/gui-font.c | 45 ++++++++++++++++++++++++++++++++++++ src/util/gui/font.h | 1 + src/util/gui/menu.c | 20 ++++++++-------- 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/platform/3ds/gui-font.c b/src/platform/3ds/gui-font.c index 1b3e483ec..aca90e9a7 100644 --- a/src/platform/3ds/gui-font.c +++ b/src/platform/3ds/gui-font.c @@ -124,3 +124,14 @@ void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment break; } } + +void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) { + ctrActivateTexture(&font->icons); + + if (icon >= GUI_ICON_MAX) { + return; + } + + struct GUIIconMetric metric = defaultIconMetrics[icon]; + ctrAddRectScaled(color, x, y, w, h, metric.x, metric.y, metric.width, metric.height); +} diff --git a/src/platform/psp2/gui-font.c b/src/platform/psp2/gui-font.c index 5d23e67d2..1878b039a 100644 --- a/src/platform/psp2/gui-font.c +++ b/src/platform/psp2/gui-font.c @@ -54,12 +54,12 @@ void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, glyph = '?'; } struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph]; - vita2d_draw_texture_tint_part_scale(font->tex, x, y - GLYPH_HEIGHT + metric.padding.top * 2, + vita2d_draw_texture_tint_part(font->tex, x, y - GLYPH_HEIGHT + metric.padding.top * 2, (glyph & 15) * CELL_WIDTH + metric.padding.left * 2, (glyph >> 4) * CELL_HEIGHT + metric.padding.top * 2, CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2, - 1, 1, color); + color); } void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) { @@ -86,13 +86,13 @@ void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment switch (orient) { case GUI_ORIENT_HMIRROR: - vita2d_draw_texture_tint_part_scale(font->icons, x, y, + vita2d_draw_texture_tint_part_scale(font->icons, x + metric.width * 2, y, metric.x * 2, metric.y * 2, metric.width * 2, metric.height * 2, -1, 1, color); return; case GUI_ORIENT_VMIRROR: - vita2d_draw_texture_tint_part_scale(font->icons, x, y, + vita2d_draw_texture_tint_part_scale(font->icons, x, y + metric.height * 2, metric.x * 2, metric.y * 2, metric.width * 2, metric.height * 2, 1, -1, color); @@ -107,3 +107,14 @@ void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment break; } } + +void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) { + if (icon >= GUI_ICON_MAX) { + return; + } + struct GUIIconMetric metric = defaultIconMetrics[icon]; + vita2d_draw_texture_tint_part_scale(font->icons, x, y, + metric.x * 2, metric.y * 2, + metric.width * 2, metric.height * 2, + w / (float) metric.width, h / (float) metric.height, color); +} diff --git a/src/platform/wii/gui-font.c b/src/platform/wii/gui-font.c index 731490e6a..b4f6ffae4 100644 --- a/src/platform/wii/gui-font.c +++ b/src/platform/wii/gui-font.c @@ -180,3 +180,48 @@ void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment GX_TexCoord2f32(u[3], v[3]); GX_End(); } + +void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) { + if (icon >= GUI_ICON_MAX) { + return; + } + + color = (color >> 24) | (color << 8); + GXTexObj tex; + + struct GUIFont* ncfont = font; + TPL_GetTexture(&ncfont->iconsTdf, 0, &tex); + GX_LoadTexObj(&tex, GX_TEXMAP0); + + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + + struct GUIIconMetric metric = defaultIconMetrics[icon]; + + float u[4]; + float v[4]; + + u[0] = u[3] = metric.x / 256.f; + u[1] = u[2] = (metric.x + metric.width) / 256.f; + v[0] = v[1] = (metric.y + metric.height) / 64.f; + v[2] = v[3] = metric.y / 64.f; + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + GX_Position2s16(x, y + h); + GX_Color1u32(color); + GX_TexCoord2f32(u[0], v[0]); + + GX_Position2s16(x + w, y + h); + GX_Color1u32(color); + GX_TexCoord2f32(u[1], v[1]); + + GX_Position2s16(x + w, y); + GX_Color1u32(color); + GX_TexCoord2f32(u[2], v[2]); + + GX_Position2s16(x, y); + GX_Color1u32(color); + GX_TexCoord2f32(u[3], v[3]); + GX_End(); +} diff --git a/src/util/gui/font.h b/src/util/gui/font.h index f422d61ee..91dac288a 100644 --- a/src/util/gui/font.h +++ b/src/util/gui/font.h @@ -81,5 +81,6 @@ void GUIFontPrintf(const struct GUIFont*, int x, int y, enum GUIAlignment, uint3 void GUIFontPrint(const struct GUIFont*, int x, int y, enum GUIAlignment, uint32_t color, const char* text); void GUIFontDrawGlyph(const struct GUIFont*, int x, int y, uint32_t color, uint32_t glyph); void GUIFontDrawIcon(const struct GUIFont*, int x, int y, enum GUIAlignment, enum GUIOrientation, uint32_t color, enum GUIIcon); +void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon); #endif diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 283468542..8dbec9db5 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -97,7 +97,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men ++menu->index; } else if (cy <= params->height - lineHeight && cy > 2 * lineHeight) { size_t location = cy - 2 * lineHeight; - location *= GUIMenuItemListSize(&menu->items); + location *= GUIMenuItemListSize(&menu->items) - 1; menu->index = location / (params->height - 3 * lineHeight); } } @@ -149,10 +149,10 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men int color = 0xE0A0A0A0; if (i == menu->index) { color = 0xFFFFFFFF; - GUIFontDrawIcon(params->font, 2, y, GUI_ALIGN_BOTTOM | GUI_ALIGN_LEFT, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_POINTER); + GUIFontDrawIcon(params->font, lineHeight * 0.8f, y, GUI_ALIGN_BOTTOM | GUI_ALIGN_RIGHT, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_POINTER); } struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, i); - GUIFontPrintf(params->font, 0, y, GUI_ALIGN_LEFT, color, " %s", item->title); + GUIFontPrint(params->font, lineHeight, y, GUI_ALIGN_LEFT, color, item->title); if (item->validStates && item->validStates[item->state]) { GUIFontPrintf(params->font, params->width, y, GUI_ALIGN_RIGHT, color, "%s ", item->validStates[item->state]); } @@ -163,15 +163,13 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men } if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) { - y = 2 * lineHeight; - GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); - for (; y < params->height - 16; y += 16) { - GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); - } - GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); - size_t top = 2 * lineHeight; - y = menu->index * (y - top - 16) / GUIMenuItemListSize(&menu->items); + size_t bottom = params->height - 8; + GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); + GUIFontDrawIconSize(params->font, params->width - 9, top, 2, bottom - top, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); + GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); + + y = menu->index * (bottom - top - 16) / GUIMenuItemListSize(&menu->items); GUIFontDrawIcon(params->font, params->width - 8, top + y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_THUMB); } From 66d005030f5e9816a13e21abbbf2fc3f170a8150 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 30 Jan 2016 23:35:29 -0800 Subject: [PATCH 54/68] 3DS: DSP audio --- src/platform/3ds/main.c | 127 ++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index fe1b74b3c..166c10f00 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -32,8 +32,9 @@ static enum ScreenMode { #define _3DS_INPUT 0x3344534B -#define AUDIO_SAMPLES 0x80 -#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 24) +#define AUDIO_SAMPLES 384 +#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 16) +#define DSP_BUFFERS 4 FS_Archive sdmcArchive; @@ -43,7 +44,12 @@ static struct GBA3DSRotationSource { angularRate gyro; } rotation; -static bool hasSound; +static enum { + NO_SOUND, + DSP_SUPPORTED, + CSND_SUPPORTED +} hasSound; + // TODO: Move into context static struct GBAVideoSoftwareRenderer renderer; static struct GBAAVStream stream; @@ -53,6 +59,8 @@ static size_t audioPos = 0; static struct ctrTexture gbaOutputTexture; static int guiDrawn; static int screenCleanup; +static ndspWaveBuf dspBuffer[DSP_BUFFERS]; +static int bufferId = 0; static aptHookCookie cookie; @@ -84,9 +92,17 @@ static void _cleanup(void) { gfxExit(); - if (hasSound) { + if (hasSound != NO_SOUND) { linearFree(audioLeft); + } + + if (hasSound == CSND_SUPPORTED) { linearFree(audioRight); + csndExit(); + } + + if (hasSound == DSP_SUPPORTED) { + ndspExit(); } csndExit(); @@ -98,14 +114,18 @@ static void _aptHook(APT_HookType hook, void* user) { switch (hook) { case APTHOOK_ONSUSPEND: case APTHOOK_ONSLEEP: - CSND_SetPlayState(8, 0); - CSND_SetPlayState(9, 0); - csndExecCmds(false); + if (hasSound == CSND_SUPPORTED) { + CSND_SetPlayState(8, 0); + CSND_SetPlayState(9, 0); + csndExecCmds(false); + } break; case APTHOOK_ONEXIT: - CSND_SetPlayState(8, 0); - CSND_SetPlayState(9, 0); - csndExecCmds(false); + if (hasSound == CSND_SUPPORTED) { + CSND_SetPlayState(8, 0); + CSND_SetPlayState(9, 0); + csndExecCmds(false); + } _cleanup(); exit(0); break; @@ -118,8 +138,7 @@ static void _map3DSKey(struct GBAInputMap* map, int ctrKey, enum GBAKey key) { GBAInputBindKey(map, _3DS_INPUT, __builtin_ctz(ctrKey), key); } -static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, void* right, u32 size) -{ +static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, void* right, u32 size) { u32 pleft = 0, pright = 0; int loopMode = (flags >> 10) & 3; @@ -231,7 +250,7 @@ static void _guiFinish(void) { static void _setup(struct GBAGUIRunner* runner) { runner->context.gba->rotationSource = &rotation.d; - if (hasSound) { + if (hasSound != NO_SOUND) { runner->context.gba->stream = &stream; } @@ -273,12 +292,16 @@ static void _gameLoaded(struct GBAGUIRunner* runner) { blip_set_rates(runner->context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 32768 * ratio); blip_set_rates(runner->context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 32768 * ratio); #endif - if (hasSound) { + if (hasSound != NO_SOUND) { + audioPos = 0; + } + if (hasSound == CSND_SUPPORTED) { memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); memset(audioRight, 0, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); - audioPos = 0; _csndPlaySound(SOUND_REPEAT | SOUND_FORMAT_16BIT, 32768, 1.0, audioLeft, audioRight, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); csndExecCmds(false); + } else if (hasSound == DSP_SUPPORTED) { + memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * 2 * sizeof(int16_t)); } unsigned mode; if (GBAConfigGetUIntValue(&runner->context.config, "screenMode", &mode) && mode != screenMode) { @@ -288,7 +311,7 @@ static void _gameLoaded(struct GBAGUIRunner* runner) { } static void _gameUnloaded(struct GBAGUIRunner* runner) { - if (hasSound) { + if (hasSound == CSND_SUPPORTED) { CSND_SetPlayState(8, 0); CSND_SetPlayState(9, 0); csndExecCmds(false); @@ -355,7 +378,7 @@ static void _drawFrame(struct GBAGUIRunner* runner, bool faded) { GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_FLIP_VERT(1)); #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF - if (!hasSound) { + if (hasSound == NO_SOUND) { blip_clear(runner->context.gba->audio.left); blip_clear(runner->context.gba->audio.right); } @@ -490,23 +513,45 @@ static int32_t _readGyroZ(struct GBARotationSource* source) { static void _postAudioBuffer(struct GBAAVStream* stream, struct GBAAudio* audio) { UNUSED(stream); + if (hasSound == CSND_SUPPORTED) { #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF - blip_read_samples(audio->left, &audioLeft[audioPos], AUDIO_SAMPLES, false); - blip_read_samples(audio->right, &audioRight[audioPos], AUDIO_SAMPLES, false); + blip_read_samples(audio->left, &audioLeft[audioPos], AUDIO_SAMPLES, false); + blip_read_samples(audio->right, &audioRight[audioPos], AUDIO_SAMPLES, false); #elif RESAMPLE_LIBRARY == RESAMPLE_NN - GBAAudioCopy(audio, &audioLeft[audioPos], &audioRight[audioPos], AUDIO_SAMPLES); + GBAAudioCopy(audio, &audioLeft[audioPos], &audioRight[audioPos], AUDIO_SAMPLES); #endif - GSPGPU_FlushDataCache(&audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); - GSPGPU_FlushDataCache(&audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); - audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER; - if (audioPos == AUDIO_SAMPLES * 3) { - u8 playing = 0; - csndIsPlaying(0x8, &playing); - if (!playing) { - CSND_SetPlayState(0x8, 1); - CSND_SetPlayState(0x9, 1); - csndExecCmds(false); + GSPGPU_FlushDataCache(&audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); + GSPGPU_FlushDataCache(&audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); + audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER; + if (audioPos == AUDIO_SAMPLES * 3) { + u8 playing = 0; + csndIsPlaying(0x8, &playing); + if (!playing) { + CSND_SetPlayState(0x8, 1); + CSND_SetPlayState(0x9, 1); + csndExecCmds(false); + } } + } else if (hasSound == DSP_SUPPORTED) { + int startId = bufferId; + while (dspBuffer[bufferId].status == NDSP_WBUF_QUEUED || dspBuffer[bufferId].status == NDSP_WBUF_PLAYING) { + bufferId = (bufferId + 1) & (DSP_BUFFERS - 1); + if (bufferId == startId) { + blip_clear(audio->left); + blip_clear(audio->right); + return; + } + } + void* tmpBuf = dspBuffer[bufferId].data_pcm16; + memset(&dspBuffer[bufferId], 0, sizeof(dspBuffer[bufferId])); + dspBuffer[bufferId].data_pcm16 = tmpBuf; + dspBuffer[bufferId].nsamples = AUDIO_SAMPLES; +#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF + blip_read_samples(audio->left, dspBuffer[bufferId].data_pcm16, AUDIO_SAMPLES, true); + blip_read_samples(audio->right, dspBuffer[bufferId].data_pcm16 + 1, AUDIO_SAMPLES, true); +#endif + DSP_FlushDataCache(dspBuffer[bufferId].data_pcm16, AUDIO_SAMPLES * 2 * sizeof(int16_t)); + ndspChnWaveBufAdd(0, &dspBuffer[bufferId]); } } @@ -527,9 +572,27 @@ int main() { aptHook(&cookie, _aptHook, 0); ptmuInit(); - hasSound = !csndInit(); + hasSound = NO_SOUND; + if (!ndspInit()) { + hasSound = DSP_SUPPORTED; + ndspSetOutputMode(NDSP_OUTPUT_STEREO); + ndspSetOutputCount(1); + ndspChnReset(0); + ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); + ndspChnSetInterp(0, NDSP_INTERP_NONE); + ndspChnSetRate(0, 0x8000); + ndspChnWaveBufClear(0); + audioLeft = linearMemAlign(AUDIO_SAMPLES * DSP_BUFFERS * 2 * sizeof(int16_t), 0x80); + memset(dspBuffer, 0, sizeof(dspBuffer)); + int i; + for (i = 0; i < DSP_BUFFERS; ++i) { + dspBuffer[i].data_pcm16 = &audioLeft[AUDIO_SAMPLES * i * 2]; + dspBuffer[i].nsamples = AUDIO_SAMPLES; + } + } - if (hasSound) { + if (hasSound == NO_SOUND && !csndInit()) { + hasSound = CSND_SUPPORTED; audioLeft = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80); audioRight = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80); } From 6646baa3b3c07f123059c9d101d167444efb101a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 12:24:09 -0800 Subject: [PATCH 55/68] Qt: Add ability to force old versions of OpenGL --- src/platform/qt/Display.cpp | 16 ++++++++++------ src/platform/qt/Display.h | 5 ++++- src/platform/qt/DisplayGL.cpp | 12 ++++++++++-- src/platform/qt/DisplayGL.h | 2 +- src/platform/qt/SettingsView.cpp | 9 ++++++++- src/platform/sdl/main.c | 2 +- src/platform/sdl/main.h | 6 +++--- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 014162562..5d76a5144 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -14,30 +14,34 @@ extern "C" { using namespace QGBA; -#ifdef BUILD_GL +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) Display::Driver Display::s_driver = Display::Driver::OPENGL; #else Display::Driver Display::s_driver = Display::Driver::QT; #endif Display* Display::create(QWidget* parent) { -#ifdef BUILD_GL +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) QGLFormat format(QGLFormat(QGL::Rgba | QGL::DoubleBuffer)); format.setSwapInterval(1); #endif switch (s_driver) { -#ifdef BUILD_GL +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) case Driver::OPENGL: - return new DisplayGL(format, parent); + return new DisplayGL(format, false, parent); +#endif +#ifdef BUILD_GL + case Driver::OPENGL1: + return new DisplayGL(format, true, parent); #endif case Driver::QT: return new DisplayQt(parent); default: -#ifdef BUILD_GL - return new DisplayGL(format, parent); +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) + return new DisplayGL(format, false, parent); #else return new DisplayQt(parent); #endif diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index 097e4c12f..a4145f6df 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -22,8 +22,11 @@ Q_OBJECT public: enum class Driver { QT = 0, -#ifdef BUILD_GL +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) OPENGL = 1, +#endif +#ifdef BUILD_GL + OPENGL1 = 2, #endif }; diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index c05ecdf1c..91ddaf68f 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -24,14 +24,22 @@ extern "C" { using namespace QGBA; -DisplayGL::DisplayGL(const QGLFormat& format, QWidget* parent) +DisplayGL::DisplayGL(const QGLFormat& format, bool force1, QWidget* parent) : Display(parent) , m_isDrawing(false) , m_gl(new EmptyGLWidget(format, this)) , m_drawThread(nullptr) , m_context(nullptr) { - m_painter = new PainterGL(m_gl, QGLFormat::openGLVersionFlags()); + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + if (force1) { + versions &= QGLFormat::OpenGL_Version_1_1 | + QGLFormat::OpenGL_Version_1_2 | + QGLFormat::OpenGL_Version_1_3 | + QGLFormat::OpenGL_Version_1_4 | + QGLFormat::OpenGL_Version_1_5; + } + m_painter = new PainterGL(m_gl, versions); m_gl->setMouseTracking(true); m_gl->setAttribute(Qt::WA_TransparentForMouseEvents); // This doesn't seem to work? } diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 39fa1e308..fa0b9e514 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -45,7 +45,7 @@ class DisplayGL : public Display { Q_OBJECT public: - DisplayGL(const QGLFormat& format, QWidget* parent = nullptr); + DisplayGL(const QGLFormat& format, bool force1 = false, QWidget* parent = nullptr); ~DisplayGL(); bool isDrawing() const override { return m_isDrawing; } diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 48ed5e4e8..ac7df35a3 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -114,13 +114,20 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC m_ui.displayDriver->setCurrentIndex(m_ui.displayDriver->count() - 1); } -#ifdef BUILD_GL +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) m_ui.displayDriver->addItem(tr("OpenGL"), static_cast(Display::Driver::OPENGL)); if (displayDriver.isNull() || displayDriver.toInt() == static_cast(Display::Driver::OPENGL)) { m_ui.displayDriver->setCurrentIndex(m_ui.displayDriver->count() - 1); } #endif +#ifdef BUILD_GL + m_ui.displayDriver->addItem(tr("OpenGL (force version 1.x)"), static_cast(Display::Driver::OPENGL1)); + if (displayDriver.isNull() || displayDriver.toInt() == static_cast(Display::Driver::OPENGL1)) { + m_ui.displayDriver->setCurrentIndex(m_ui.displayDriver->count() - 1); + } +#endif + connect(m_ui.biosBrowse, SIGNAL(clicked()), this, SLOT(selectBios())); connect(m_ui.buttonBox, SIGNAL(accepted()), this, SLOT(updateConfig())); connect(m_ui.buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button) { diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index ffc801413..ebbbaae93 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -95,7 +95,7 @@ int main(int argc, char** argv) { #ifdef BUILD_GL GBASDLGLCreate(&renderer); -#elif defined(BUILD_GLES2) +#elif defined(BUILD_GLES2) || defined(USE_EPOXY) GBASDLGLES2Create(&renderer); #else GBASDLSWCreate(&renderer); diff --git a/src/platform/sdl/main.h b/src/platform/sdl/main.h index 5504fe988..28ea116a4 100644 --- a/src/platform/sdl/main.h +++ b/src/platform/sdl/main.h @@ -26,7 +26,7 @@ #pragma GCC diagnostic pop #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(USE_EPOXY) #include "platform/opengl/gles2.h" #endif @@ -63,7 +63,7 @@ struct SDLSoftwareRenderer { #ifdef BUILD_GL struct GBAGLContext gl; #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(USE_EPOXY) struct GBAGLES2Context gl2; #endif @@ -92,7 +92,7 @@ void GBASDLSWCreate(struct SDLSoftwareRenderer* renderer); void GBASDLGLCreate(struct SDLSoftwareRenderer* renderer); #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(USE_EPOXY) void GBASDLGLES2Create(struct SDLSoftwareRenderer* renderer); #endif #endif From 1fce327192bef81e4ddc1ce1acde3688c74fab59 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 14:08:28 -0800 Subject: [PATCH 56/68] 3DS: Enable L2 cache on n3DS --- src/platform/3ds/cia.rsf.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/3ds/cia.rsf.in b/src/platform/3ds/cia.rsf.in index a6ebf7ff8..5c91583da 100644 --- a/src/platform/3ds/cia.rsf.in +++ b/src/platform/3ds/cia.rsf.in @@ -92,6 +92,7 @@ AccessControlInfo: MaxCpu : 0x9E # Default CpuSpeed : 804mhz + EnableL2Cache : true DisableDebug : true EnableForceDebug : false From fbea708ed4c60caf748834daef1ca6b0f7f6c6b7 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 14:35:27 -0800 Subject: [PATCH 57/68] GUI: Fix top button on scrollbars being upside down --- src/util/gui/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 8dbec9db5..65c2d038f 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -165,7 +165,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) { size_t top = 2 * lineHeight; size_t bottom = params->height - 8; - GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); + GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); GUIFontDrawIconSize(params->font, params->width - 9, top, 2, bottom - top, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); From 78ef8523ac3c49ccce9108427895dfd49cd829ce Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 14:56:50 -0800 Subject: [PATCH 58/68] Qt: Make key binding fields have a width relative to its height --- src/platform/qt/KeyEditor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/qt/KeyEditor.cpp b/src/platform/qt/KeyEditor.cpp index 52877bdc3..ba39b69a3 100644 --- a/src/platform/qt/KeyEditor.cpp +++ b/src/platform/qt/KeyEditor.cpp @@ -9,6 +9,7 @@ #include "GamepadButtonEvent.h" #include "ShortcutController.h" +#include #include using namespace QGBA; @@ -72,7 +73,8 @@ void KeyEditor::clearAxis() { QSize KeyEditor::sizeHint() const { QSize hint = QLineEdit::sizeHint(); - hint.setWidth(50); + QFontMetrics fm(font()); + hint.setWidth(fm.height() * 3); return hint; } From c69c34ab2d419fa5ca605094e4afbb8f9e406a47 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 23:52:03 -0800 Subject: [PATCH 59/68] SDL: Fix crash when attempting to sample sensors with no controller attached --- src/platform/sdl/sdl-events.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 8ca7a617b..323877e60 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -599,6 +599,9 @@ static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) { #endif static int32_t _readTilt(struct GBASDLPlayer* player, int axis) { + if (!player->joystick) { + return 0; + } return SDL_JoystickGetAxis(player->joystick->joystick, axis) * 0x3800; } @@ -621,6 +624,9 @@ static int32_t _GBASDLReadGyroZ(struct GBARotationSource* source) { static void _GBASDLRotationSample(struct GBARotationSource* source) { struct GBASDLRotation* rotation = (struct GBASDLRotation*) source; SDL_JoystickUpdate(); + if (!rotation->p->joystick) { + return; + } int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX); int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY); From d53004650d5fbf3bc5b3f830e4fce604bee70132 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 1 Feb 2016 00:01:29 -0800 Subject: [PATCH 60/68] Qt: Set window flags on dialogs --- src/platform/qt/ROMInfo.cpp | 4 +++- src/platform/qt/ShaderSelector.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/ROMInfo.cpp b/src/platform/qt/ROMInfo.cpp index 6f144d209..10f0fb9f1 100644 --- a/src/platform/qt/ROMInfo.cpp +++ b/src/platform/qt/ROMInfo.cpp @@ -14,7 +14,9 @@ extern "C" { using namespace QGBA; -ROMInfo::ROMInfo(GameController* controller, QWidget* parent) { +ROMInfo::ROMInfo(GameController* controller, QWidget* parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) +{ m_ui.setupUi(this); if (!controller->isLoaded()) { diff --git a/src/platform/qt/ShaderSelector.cpp b/src/platform/qt/ShaderSelector.cpp index 599a1e5fe..253303132 100644 --- a/src/platform/qt/ShaderSelector.cpp +++ b/src/platform/qt/ShaderSelector.cpp @@ -28,7 +28,7 @@ extern "C" { using namespace QGBA; ShaderSelector::ShaderSelector(Display* display, ConfigController* config, QWidget* parent) - : QDialog(parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) , m_display(display) , m_config(config) , m_shaderPath("") From 8e99508717c7c5e2316c50a03dd156d4d86bceeb Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 20:09:50 -0800 Subject: [PATCH 61/68] GUI: Show icons in key remapping --- src/platform/3ds/gui-font.c | 21 ++++++++++++++++++++- src/platform/psp2/gui-font.c | 21 ++++++++++++++++++++- src/platform/psp2/main.c | 8 ++++---- src/platform/wii/gui-font.c | 26 ++++++++++++++++++++++++++ src/platform/wii/main.c | 12 ++++++------ src/util/gui/font-metrics.c | 2 +- src/util/gui/font.c | 33 +++++++++++++++++++++++++++------ src/util/gui/font.h | 1 + src/util/gui/menu.c | 7 ++++++- 9 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/platform/3ds/gui-font.c b/src/platform/3ds/gui-font.c index aca90e9a7..7bec4ab44 100644 --- a/src/platform/3ds/gui-font.c +++ b/src/platform/3ds/gui-font.c @@ -70,6 +70,25 @@ unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { return defaultFontMetrics[glyph].width; } +void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) { + UNUSED(font); + if (icon >= GUI_ICON_MAX) { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } + } else { + if (w) { + *w = defaultIconMetrics[icon].width; + } + if (h) { + *h = defaultIconMetrics[icon].height; + } + } +} + void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) { ctrActivateTexture(&font->texture); @@ -133,5 +152,5 @@ void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, } struct GUIIconMetric metric = defaultIconMetrics[icon]; - ctrAddRectScaled(color, x, y, w, h, metric.x, metric.y, metric.width, metric.height); + ctrAddRectScaled(color, x, y, w ? w : metric.width, h ? h : metric.height, metric.x, metric.y, metric.width, metric.height); } diff --git a/src/platform/psp2/gui-font.c b/src/platform/psp2/gui-font.c index 1878b039a..aa1e6cdc1 100644 --- a/src/platform/psp2/gui-font.c +++ b/src/platform/psp2/gui-font.c @@ -49,6 +49,25 @@ unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { return defaultFontMetrics[glyph].width * 2; } +void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) { + UNUSED(font); + if (icon >= GUI_ICON_MAX) { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } + } else { + if (w) { + *w = defaultIconMetrics[icon].width * 2; + } + if (h) { + *h = defaultIconMetrics[icon].height * 2; + } + } +} + void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, uint32_t glyph) { if (glyph > 0x7F) { glyph = '?'; @@ -116,5 +135,5 @@ void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, vita2d_draw_texture_tint_part_scale(font->icons, x, y, metric.x * 2, metric.y * 2, metric.width * 2, metric.height * 2, - w / (float) metric.width, h / (float) metric.height, color); + w ? (w / (float) metric.width) : 1, h ? (h / (float) metric.height) : 1, color); } diff --git a/src/platform/psp2/main.c b/src/platform/psp2/main.c index 708d9dd36..b16abeae3 100644 --- a/src/platform/psp2/main.c +++ b/src/platform/psp2/main.c @@ -136,10 +136,10 @@ int main() { "R", 0, // L2? 0, // R2? - "Triangle", - "Circle", - "Cross", - "Square" + "\1\xC", + "\1\xA", + "\1\xB", + "\1\xD" }, .nKeys = 16 }, diff --git a/src/platform/wii/gui-font.c b/src/platform/wii/gui-font.c index b4f6ffae4..8ca4c6550 100644 --- a/src/platform/wii/gui-font.c +++ b/src/platform/wii/gui-font.c @@ -65,6 +65,25 @@ unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { return defaultFontMetrics[glyph].width * 2; } +void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) { + UNUSED(font); + if (icon >= GUI_ICON_MAX) { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } + } else { + if (w) { + *w = defaultIconMetrics[icon].width * 2; + } + if (h) { + *h = defaultIconMetrics[icon].height * 2; + } + } +} + void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, uint32_t glyph) { color = (color >> 24) | (color << 8); GXTexObj tex; @@ -202,6 +221,13 @@ void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, float u[4]; float v[4]; + if (!h) { + h = metric.height * 2; + } + if (!w) { + w = metric.width * 2; + } + u[0] = u[3] = metric.x / 256.f; u[1] = u[2] = (metric.x + metric.width) / 256.f; v[0] = v[1] = (metric.y + metric.height) / 64.f; diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index c44092198..e3b2b9524 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -264,15 +264,15 @@ int main(int argc, char* argv[]) { "1", "B", "A", - "Minus", + "-", 0, 0, - "Home", + "\1\xE", "Left", "Right", "Down", "Up", - "Plus", + "+", 0, 0, 0, @@ -311,9 +311,9 @@ int main(int argc, char* argv[]) { "ZL", 0, "R", - "Plus", - "Home", - "Minus", + "+", + "\1\xE", + "-", "L", "Down", "Right", diff --git a/src/util/gui/font-metrics.c b/src/util/gui/font-metrics.c index 3430e3b4b..684635d26 100644 --- a/src/util/gui/font-metrics.c +++ b/src/util/gui/font-metrics.c @@ -151,5 +151,5 @@ struct GUIIconMetric defaultIconMetrics[] = { [GUI_ICON_BUTTON_CROSS] = { 18, 34, 12, 11 }, [GUI_ICON_BUTTON_TRIANGLE] = { 34, 34, 12, 11 }, [GUI_ICON_BUTTON_SQUARE] = { 50, 34, 12, 11 }, - [GUI_ICON_BUTTON_HOME] = { 66, 34, 16, 16 }, + [GUI_ICON_BUTTON_HOME] = { 66, 34, 12, 11 }, }; diff --git a/src/util/gui/font.c b/src/util/gui/font.c index a24ca9466..03965bf24 100644 --- a/src/util/gui/font.c +++ b/src/util/gui/font.c @@ -5,12 +5,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "util/gui/font.h" +#include "util/string.h" + unsigned GUIFontSpanWidth(const struct GUIFont* font, const char* text) { unsigned width = 0; - size_t i; - for (i = 0; text[i]; ++i) { - char c = text[i]; - width += GUIFontGlyphWidth(font, c); + size_t len = strlen(text); + while (len) { + uint32_t c = utf8Char(&text, &len); + if (c == '\1') { + c = utf8Char(&text, &len); + if (c < GUI_ICON_MAX) { + unsigned w; + GUIFontIconMetrics(font, c, &w, 0); + width += w; + } + } else { + width += GUIFontGlyphWidth(font, c); + } } return width; } @@ -29,8 +40,18 @@ void GUIFontPrint(const struct GUIFont* font, int x, int y, enum GUIAlignment al size_t len = strlen(text); while (len) { uint32_t c = utf8Char(&text, &len); - GUIFontDrawGlyph(font, x, y, color, c); - x += GUIFontGlyphWidth(font, c); + if (c == '\1') { + c = utf8Char(&text, &len); + if (c < GUI_ICON_MAX) { + GUIFontDrawIcon(font, x, y, GUI_ALIGN_BOTTOM, GUI_ORIENT_0, color, c); + unsigned w; + GUIFontIconMetrics(font, c, &w, 0); + x += w; + } + } else { + GUIFontDrawGlyph(font, x, y, color, c); + x += GUIFontGlyphWidth(font, c); + } } } diff --git a/src/util/gui/font.h b/src/util/gui/font.h index 91dac288a..7c936ffb9 100644 --- a/src/util/gui/font.h +++ b/src/util/gui/font.h @@ -75,6 +75,7 @@ struct GUIIconMetric { unsigned GUIFontHeight(const struct GUIFont*); unsigned GUIFontGlyphWidth(const struct GUIFont*, uint32_t glyph); unsigned GUIFontSpanWidth(const struct GUIFont*, const char* text); +void GUIFontIconMetrics(const struct GUIFont*, enum GUIIcon icon, unsigned* w, unsigned* h); ATTRIBUTE_FORMAT(printf, 6, 7) void GUIFontPrintf(const struct GUIFont*, int x, int y, enum GUIAlignment, uint32_t color, const char* text, ...); diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 65c2d038f..a64de2c48 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -165,8 +165,13 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) { size_t top = 2 * lineHeight; size_t bottom = params->height - 8; + unsigned w; + unsigned right; + GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_BUTTON, &right, 0); + GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_TRACK, &w, 0); + right = (right - w) / 2; GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); - GUIFontDrawIconSize(params->font, params->width - 9, top, 2, bottom - top, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); + GUIFontDrawIconSize(params->font, params->width - right - 8, top, 0, bottom - top, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); y = menu->index * (bottom - top - 16) / GUIMenuItemListSize(&menu->items); From 6af9a742bda66c3785cd13f76895558eeac77725 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 21:59:16 -0800 Subject: [PATCH 62/68] VFS: Add VDir.deleteFile --- src/platform/3ds/3ds-vfs.c | 18 ++++++++++++++++++ src/platform/psp2/sce-vfs.c | 16 ++++++++++++++++ src/util/vfs.h | 1 + src/util/vfs/vfs-devlist.c | 8 ++++++++ src/util/vfs/vfs-dirent.c | 16 ++++++++++++++++ src/util/vfs/vfs-lzma.c | 9 +++++++++ src/util/vfs/vfs-zip.c | 16 ++++++++++++++++ 7 files changed, 84 insertions(+) diff --git a/src/platform/3ds/3ds-vfs.c b/src/platform/3ds/3ds-vfs.c index 2963c78d1..24caff97d 100644 --- a/src/platform/3ds/3ds-vfs.c +++ b/src/platform/3ds/3ds-vfs.c @@ -45,6 +45,7 @@ static void _vd3dRewind(struct VDir* vd); static struct VDirEntry* _vd3dListNext(struct VDir* vd); static struct VFile* _vd3dOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vd3dOpenDir(struct VDir* vd, const char* path); +static bool _vd3dDeleteFile(struct VDir* vd, const char* path); static const char* _vd3deName(struct VDirEntry* vde); static enum VFSType _vd3deType(struct VDirEntry* vde); @@ -191,6 +192,7 @@ struct VDir* VDirOpen(const char* path) { vd3d->d.listNext = _vd3dListNext; vd3d->d.openFile = _vd3dOpenFile; vd3d->d.openDir = _vd3dOpenDir; + vd3d->d.deleteFile = _vd3dDeleteFile; vd3d->vde.d.name = _vd3deName; vd3d->vde.d.type = _vd3deType; @@ -257,6 +259,22 @@ static struct VDir* _vd3dOpenDir(struct VDir* vd, const char* path) { return vd2; } +static bool _vd3dDeleteFile(struct VDir* vd, const char* path) { + struct VDir3DS* vd3d = (struct VDir3DS*) vd; + if (!path) { + return 0; + } + const char* dir = vd3d->path; + char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); + sprintf(combined, "%s/%s", dir, path); + + // TODO: Use UTF-16 + FS_Path newPath = fsMakePath(PATH_ASCII, combined); + bool ret = !FSUSER_DeleteFile(sdmcArchive, newPath); + free(combined); + return ret; +} + static const char* _vd3deName(struct VDirEntry* vde) { struct VDirEntry3DS* vd3de = (struct VDirEntry3DS*) vde; if (!vd3de->utf8Name[0]) { diff --git a/src/platform/psp2/sce-vfs.c b/src/platform/psp2/sce-vfs.c index de057eb34..2dac02319 100644 --- a/src/platform/psp2/sce-vfs.c +++ b/src/platform/psp2/sce-vfs.c @@ -43,6 +43,7 @@ static void _vdsceRewind(struct VDir* vd); static struct VDirEntry* _vdsceListNext(struct VDir* vd); static struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path); +static bool _vdsceDeleteFile(struct VDir* vd, const char* path); static const char* _vdesceName(struct VDirEntry* vde); static enum VFSType _vdesceType(struct VDirEntry* vde); @@ -152,6 +153,7 @@ struct VDir* VDirOpen(const char* path) { vd->d.listNext = _vdsceListNext; vd->d.openFile = _vdsceOpenFile; vd->d.openDir = _vdsceOpenDir; + vd->d.deleteFile = _vdsceDeleteFile; vd->path = strdup(path); vd->de.d.name = _vdesceName; @@ -215,6 +217,20 @@ struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) { return vd2; } +bool _vdsceDeleteFile(struct VDir* vd, const char* path) { + struct VDirSce* vdsce = (struct VDirSce*) vd; + if (!path) { + return 0; + } + const char* dir = vdsce->path; + char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1)); + sprintf(combined, "%s%s%s", dir, PATH_SEP, path); + + bool ret = sceIoRemove(combined) >= 0; + free(combined); + return ret; +} + static const char* _vdesceName(struct VDirEntry* vde) { struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde; return vdesce->ent.d_name; diff --git a/src/util/vfs.h b/src/util/vfs.h index 5cc8dc203..19c71da92 100644 --- a/src/util/vfs.h +++ b/src/util/vfs.h @@ -59,6 +59,7 @@ struct VDir { struct VDirEntry* (*listNext)(struct VDir* vd); struct VFile* (*openFile)(struct VDir* vd, const char* name, int mode); struct VDir* (*openDir)(struct VDir* vd, const char* name); + bool (*deleteFile)(struct VDir* vd, const char* name); }; struct VFile* VFileOpen(const char* path, int flags); diff --git a/src/util/vfs/vfs-devlist.c b/src/util/vfs/vfs-devlist.c index 9fbbefbea..8f25feb17 100644 --- a/src/util/vfs/vfs-devlist.c +++ b/src/util/vfs/vfs-devlist.c @@ -12,6 +12,7 @@ static void _vdlRewind(struct VDir* vd); static struct VDirEntry* _vdlListNext(struct VDir* vd); static struct VFile* _vdlOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vdlOpenDir(struct VDir* vd, const char* path); +static bool _vdlDeleteFile(struct VDir* vd, const char* path); static const char* _vdleName(struct VDirEntry* vde); static enum VFSType _vdleType(struct VDirEntry* vde); @@ -38,6 +39,7 @@ struct VDir* VDeviceList() { vd->d.listNext = _vdlListNext; vd->d.openFile = _vdlOpenFile; vd->d.openDir = _vdlOpenDir; + vd->d.deleteFile = _vdlDeleteFile; vd->vde.d.name = _vdleName; vd->vde.d.type = _vdleType; @@ -93,6 +95,12 @@ static struct VDir* _vdlOpenDir(struct VDir* vd, const char* path) { return VDirOpen(path); } +static bool _vdlDeleteFile(struct VDir* vd, const char* path) { + UNUSED(vd); + UNUSED(path); + return false; +} + static const char* _vdleName(struct VDirEntry* vde) { struct VDirEntryDevList* vdle = (struct VDirEntryDevList*) vde; return vdle->name; diff --git a/src/util/vfs/vfs-dirent.c b/src/util/vfs/vfs-dirent.c index 5f37be05a..7104af808 100644 --- a/src/util/vfs/vfs-dirent.c +++ b/src/util/vfs/vfs-dirent.c @@ -15,6 +15,7 @@ static void _vdRewind(struct VDir* vd); static struct VDirEntry* _vdListNext(struct VDir* vd); static struct VFile* _vdOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vdOpenDir(struct VDir* vd, const char* path); +static bool _vdDeleteFile(struct VDir* vd, const char* path); static const char* _vdeName(struct VDirEntry* vde); static enum VFSType _vdeType(struct VDirEntry* vde); @@ -55,6 +56,7 @@ struct VDir* VDirOpen(const char* path) { vd->d.listNext = _vdListNext; vd->d.openFile = _vdOpenFile; vd->d.openDir = _vdOpenDir; + vd->d.deleteFile = _vdDeleteFile; vd->path = strdup(path); vd->de = de; @@ -121,6 +123,20 @@ struct VDir* _vdOpenDir(struct VDir* vd, const char* path) { return vd2; } +bool _vdDeleteFile(struct VDir* vd, const char* path) { + struct VDirDE* vdde = (struct VDirDE*) vd; + if (!path) { + return false; + } + const char* dir = vdde->path; + char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); + sprintf(combined, "%s%s%s", dir, PATH_SEP, path); + + bool ret = !unlink(combined); + free(combined); + return ret; +} + const char* _vdeName(struct VDirEntry* vde) { struct VDirEntryDE* vdede = (struct VDirEntryDE*) vde; if (vdede->ent) { diff --git a/src/util/vfs/vfs-lzma.c b/src/util/vfs/vfs-lzma.c index 6867ec456..fe2778ede 100644 --- a/src/util/vfs/vfs-lzma.c +++ b/src/util/vfs/vfs-lzma.c @@ -63,6 +63,7 @@ static void _vd7zRewind(struct VDir* vd); static struct VDirEntry* _vd7zListNext(struct VDir* vd); static struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vd7zOpenDir(struct VDir* vd, const char* path); +static bool _vd7zDeleteFile(struct VDir* vd, const char* path); static const char* _vde7zName(struct VDirEntry* vde); static enum VFSType _vde7zType(struct VDirEntry* vde); @@ -113,6 +114,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) { vd->d.listNext = _vd7zListNext; vd->d.openFile = _vd7zOpenFile; vd->d.openDir = _vd7zOpenDir; + vd->d.deleteFile = _vd7zDeleteFile; return &vd->d; } @@ -309,6 +311,13 @@ struct VDir* _vd7zOpenDir(struct VDir* vd, const char* path) { return 0; } +bool _vd7zDeleteFile(struct VDir* vd, const char* path) { + UNUSED(vd); + UNUSED(path); + // TODO + return false; +} + bool _vf7zSync(struct VFile* vf, const void* memory, size_t size) { UNUSED(vf); UNUSED(memory); diff --git a/src/util/vfs/vfs-zip.c b/src/util/vfs/vfs-zip.c index 0c1f95f5a..83936f6e2 100644 --- a/src/util/vfs/vfs-zip.c +++ b/src/util/vfs/vfs-zip.c @@ -74,6 +74,7 @@ static void _vdzRewind(struct VDir* vd); static struct VDirEntry* _vdzListNext(struct VDir* vd); static struct VFile* _vdzOpenFile(struct VDir* vd, const char* path, int mode); static struct VDir* _vdzOpenDir(struct VDir* vd, const char* path); +static bool _vdzDeleteFile(struct VDir* vd, const char* path); static const char* _vdezName(struct VDirEntry* vde); static enum VFSType _vdezType(struct VDirEntry* vde); @@ -172,6 +173,7 @@ struct VDir* VDirOpenZip(const char* path, int flags) { vd->d.listNext = _vdzListNext; vd->d.openFile = _vdzOpenFile; vd->d.openDir = _vdzOpenDir; + vd->d.deleteFile = _vdzDeleteFile; vd->z = z; #ifndef USE_LIBZIP @@ -410,6 +412,13 @@ struct VDir* _vdzOpenDir(struct VDir* vd, const char* path) { return 0; } +bool _vdzDeleteFile(struct VDir* vd, const char* path) { + UNUSED(vd); + UNUSED(path); + // TODO + return false; +} + bool _vfzSync(struct VFile* vf, const void* memory, size_t size) { UNUSED(vf); UNUSED(memory); @@ -624,6 +633,13 @@ struct VDir* _vdzOpenDir(struct VDir* vd, const char* path) { return 0; } +bool _vdzDeleteFile(struct VDir* vd, const char* path) { + UNUSED(vd); + UNUSED(path); + // TODO + return false; +} + bool _vfzSync(struct VFile* vf, const void* memory, size_t size) { UNUSED(vf); UNUSED(memory); From ed84d5cff09717ada956753b806435be4e74e248 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 31 Jan 2016 21:59:43 -0800 Subject: [PATCH 63/68] GBA: Add GBADeleteState --- src/gba/serialize.c | 8 ++++++++ src/gba/serialize.h | 1 + src/platform/qt/GameController.cpp | 5 +---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 1e6c48061..44daecda5 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -206,6 +206,14 @@ struct VFile* GBAGetState(struct GBA* gba, struct VDir* dir, int slot, bool writ return dir->openFile(dir, path, write ? (O_CREAT | O_TRUNC | O_RDWR) : O_RDONLY); } +void GBADeleteState(struct GBA* gba, struct VDir* dir, int slot) { + char basename[PATH_MAX]; + separatePath(gba->activeFile, 0, basename, 0); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s.ss%i", basename, slot); + dir->deleteFile(dir, path); +} + #ifdef USE_PNG static bool _savePNGState(struct GBA* gba, struct VFile* vf, struct GBAExtdata* extdata) { unsigned stride; diff --git a/src/gba/serialize.h b/src/gba/serialize.h index 97d4a6ee8..dd4b29c8b 100644 --- a/src/gba/serialize.h +++ b/src/gba/serialize.h @@ -366,6 +366,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state); bool GBASaveState(struct GBAThread* thread, struct VDir* dir, int slot, int flags); bool GBALoadState(struct GBAThread* thread, struct VDir* dir, int slot, int flags); struct VFile* GBAGetState(struct GBA* gba, struct VDir* dir, int slot, bool write); +void GBADeleteState(struct GBA* thread, struct VDir* dir, int slot); bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags); bool GBALoadStateNamed(struct GBA* gba, struct VFile* vf, int flags); diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 7722b7715..c409d8103 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -115,10 +115,7 @@ GameController::GameController(QObject* parent) controller->m_fpsTarget = context->fpsTarget; if (context->dirs.state && GBALoadState(context, context->dirs.state, 0, controller->m_loadStateFlags)) { - VFile* vf = GBAGetState(context->gba, context->dirs.state, 0, true); - if (vf) { - vf->truncate(vf, 0); - } + GBADeleteState(context->gba, context->dirs.state, 0); } QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context)); }; From 1f1bd3bd05b6a2a49ed211d0f09ace81e5e2490f Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 2 Feb 2016 20:41:39 -0800 Subject: [PATCH 64/68] Wii: Increase sensitivity of controller axes --- src/platform/wii/main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index e3b2b9524..cf35ff13e 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -426,18 +426,18 @@ static uint32_t _pollInput(void) { int keys = 0; int x = PAD_StickX(0); int y = PAD_StickY(0); - int w_x = WPAD_StickX(0,0); - int w_y = WPAD_StickY(0,0); - if (x < -0x40 || w_x < -0x40) { + int w_x = WPAD_StickX(0, 0); + int w_y = WPAD_StickY(0, 0); + if (x < -0x20 || w_x < -0x20) { keys |= 1 << GUI_INPUT_LEFT; } - if (x > 0x40 || w_x > 0x40) { + if (x > 0x20 || w_x > 0x20) { keys |= 1 << GUI_INPUT_RIGHT; } - if (y < -0x40 || w_y <- 0x40) { + if (y < -0x20 || w_y <- 0x20) { keys |= 1 << GUI_INPUT_DOWN; } - if (y > 0x40 || w_y > 0x40) { + if (y > 0x20 || w_y > 0x20) { keys |= 1 << GUI_INPUT_UP; } if ((padkeys & PAD_BUTTON_A) || (wiiPad & WPAD_BUTTON_2) || @@ -552,10 +552,10 @@ void _setup(struct GBAGUIRunner* runner) { _mapKey(&runner->context.inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_L, GBA_KEY_L); _mapKey(&runner->context.inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_R, GBA_KEY_R); - struct GBAAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x40, -0x40 }; + struct GBAAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x20, -0x20 }; GBAInputBindAxis(&runner->context.inputMap, GCN1_INPUT, 0, &desc); GBAInputBindAxis(&runner->context.inputMap, CLASSIC_INPUT, 0, &desc); - desc = (struct GBAAxis) { GBA_KEY_UP, GBA_KEY_DOWN, 0x40, -0x40 }; + desc = (struct GBAAxis) { GBA_KEY_UP, GBA_KEY_DOWN, 0x20, -0x20 }; GBAInputBindAxis(&runner->context.inputMap, GCN1_INPUT, 1, &desc); GBAInputBindAxis(&runner->context.inputMap, CLASSIC_INPUT, 1, &desc); From 790c77c9572c50cd8e365717e3af6010144eaa8b Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 2 Feb 2016 21:18:14 -0800 Subject: [PATCH 65/68] All: Update CHANGES for 0.4.0 --- CHANGES | 65 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/CHANGES b/CHANGES index 0d17fab74..42bc8e38e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -0.4.0: (Future) +0.4.0: (2016-02-02) Features: - Officially supported ports for the Nintendo 3DS, Wii, and PlayStation Vita - I/O viewer @@ -21,54 +21,53 @@ Features: - Controller hotplugging - Ability to store save games and active cheats within savestates Bugfixes: - - Util: Fix PowerPC PNG read/write pixel order - - VFS: Fix VFileReadline and remove _vfdReadline - - GBA Memory: Fix DMA register writing behavior - - GBA BIOS: Fix misaligned CpuSet - ARM7: Fix sign of unaligned LDRSH + - ARM7: Fix decoding of some ARM ALU instructions with shifters + - Debugger: Fix watchpoints in gdb - GBA: Fix warnings when creating and loading savestates - - GBA Memory: Fix DMAs triggering two cycles early - - GBA Hardware: Fix GPIO on big endian - - Util: Fix excessive memory allocation when decoding a PNG - GBA: Fix Iridion II savetype + - GBA BIOS: Fix misaligned CpuSet + - GBA Cheats: Fix cheats setting the Action Replay version + - GBA Hardware: Fix GPIO on big endian + - GBA Memory: Fix DMA register writing behavior + - GBA Memory: Fix DMAs triggering two cycles early - Libretro: Fix aspect ratio - Qt: Fix some potential crashes with the gamepad mapping - - Debugger: Fix watchpoints in gdb - - ARM7: Fix decoding of some ARM ALU instructions with shifters - Qt: Fix keys being mapped incorrectly when loading configuration file - - GBA Cheats: Fix cheats setting the Action Replay version + - Util: Fix PowerPC PNG read/write pixel order + - Util: Fix excessive memory allocation when decoding a PNG + - VFS: Fix VFileReadline and remove _vfdReadline Misc: - - Qt: Window size command line options are now supported - - Qt: Increase usability of key mapper - - GBA Memory: Use a dynamically sized mask for ROM memory - - ARM7: Combine shifter-immediate and shifter-register functions to reduce binary size - - SDL: Support fullscreen in SDL 1.2 - - Libretro: Use anonymous memory mappers for large blocks of memory - - Qt: Add 'Apply' button to settings window - - GBA Video: Remove lastHblank, as it is implied - - GBA Config: Add "override" layer for better one-time configuration - - SDL: Allow GBASDLAudio to be used without a thread context - All: Improved PowerPC support - All: Fix some undefined behavior warnings - - Util: Use VFile for configuration - - GBA Memory: Implement several unimplemented memory access types + - ARM7: Combine shifter-immediate and shifter-register functions to reduce binary size + - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors - GBA: Implement bad I/O register loading + - GBA: Allow jumping to OAM and palette RAM + - GBA BIOS: Finish implementing RegisterRamReset + - GBA Config: Add "override" layer for better one-time configuration + - GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING + - GBA Memory: Use a dynamically sized mask for ROM memory + - GBA Memory: Implement several unimplemented memory access types - GBA Memory: Add GBAView* functions for viewing memory directly without bus issues - - Util: Add MutexTryLock + - GBA RR: Starting from savestate now embeds the savegame + - GBA RR: Add preliminary SRAM support for VBM loading + - GBA RR: Add support for resets in movies + - GBA Video: Remove lastHblank, as it is implied + - Libretro: Use anonymous memory mappers for large blocks of memory + - Libretro: Add install target for libretro core + - Qt: Window size command line options are now supported + - Qt: Increase usability of key mapper + - Qt: Add 'Apply' button to settings window - Qt: Gray out "Skip BIOS intro" while "Use BIOS file" is unchecked - Qt: Allow use of modifier keys as input - Qt: Optimize log viewer - - GBA RR: Starting from savestate now embeds the savegame - - Libretro: Add install target for libretro core - - 3DS: Update to new ctrulib API - - GBA RR: Add preliminary SRAM support for VBM loading - - GBA RR: Add support for resets in movies - - GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING - - Debugger: Convert breakpoints and watchpoints from linked-lists to vectors - Qt: Added button for breaking into the GDB debugger - - GBA BIOS: Finish implementing RegisterRamReset - - GBA: Allow jumping to OAM and palette RAM - Qt: Add box for showing duration of rewind + - SDL: Support fullscreen in SDL 1.2 + - SDL: Allow GBASDLAudio to be used without a thread context + - Util: Use VFile for configuration + - Util: Add MutexTryLock 0.3.2: (2015-12-16) Bugfixes: From 6d0f370630355b203612368a4cb0cbc8754768b8 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Wed, 3 Feb 2016 01:08:06 -0800 Subject: [PATCH 66/68] All: Increment version number post-release --- version.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.cmake b/version.cmake index 5ae523ab4..dbb5c423f 100644 --- a/version.cmake +++ b/version.cmake @@ -2,9 +2,9 @@ if(NOT PROJECT_NAME) set(PROJECT_NAME "mGBA") endif() set(LIB_VERSION_MAJOR 0) -set(LIB_VERSION_MINOR 4) +set(LIB_VERSION_MINOR 5) set(LIB_VERSION_PATCH 0) -set(LIB_VERSION_ABI 0.4) +set(LIB_VERSION_ABI 0.5) set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}) set(SUMMARY "${PROJECT_NAME} Game Boy Advance Emulator") From be42f298dafae88507564533c7d622eda70caea8 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 7 Feb 2016 22:24:07 -0800 Subject: [PATCH 67/68] VFS: Fix reading 7z archives without rewinding first --- CHANGES | 4 ++++ src/util/vfs/vfs-lzma.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 42bc8e38e..63ba76ed9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +0.5.0: (Future) +Bugfixes: + - VFS: Fix reading 7z archives without rewinding first + 0.4.0: (2016-02-02) Features: - Officially supported ports for the Nintendo 3DS, Wii, and PlayStation Vita diff --git a/src/util/vfs/vfs-lzma.c b/src/util/vfs/vfs-lzma.c index fe2778ede..255e87322 100644 --- a/src/util/vfs/vfs-lzma.c +++ b/src/util/vfs/vfs-lzma.c @@ -103,7 +103,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) { return 0; } - vd->dirent.index = 0; + vd->dirent.index = -1; vd->dirent.utf8 = 0; vd->dirent.vd = vd; vd->dirent.d.name = _vde7zName; From 564f58c7fb2fc7c6bee5aed3fe1fcf7a13a3a43c Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 8 Feb 2016 22:32:30 -0800 Subject: [PATCH 68/68] GBA: Slightly optimize GBAProcessEvents --- CHANGES | 2 ++ src/gba/gba.c | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 63ba76ed9..6dcfef142 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ 0.5.0: (Future) Bugfixes: - VFS: Fix reading 7z archives without rewinding first +Misc: + - GBA: Slightly optimize GBAProcessEvents 0.4.0: (2016-02-02) Features: diff --git a/src/gba/gba.c b/src/gba/gba.c index 860d23cc0..08d82eee2 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -205,8 +205,19 @@ void GBASkipBIOS(struct GBA* gba) { } static void GBAProcessEvents(struct ARMCore* cpu) { + struct GBA* gba = (struct GBA*) cpu->master; + + gba->bus = cpu->prefetch[1]; + if (cpu->executionMode == MODE_THUMB) { + gba->bus |= cpu->prefetch[1] << 16; + } + + if (gba->springIRQ) { + ARMRaiseIRQ(cpu); + gba->springIRQ = 0; + } + do { - struct GBA* gba = (struct GBA*) cpu->master; int32_t cycles = cpu->nextEvent; int32_t nextEvent = INT_MAX; int32_t testEvent; @@ -216,16 +227,6 @@ static void GBAProcessEvents(struct ARMCore* cpu) { } #endif - gba->bus = cpu->prefetch[1]; - if (cpu->executionMode == MODE_THUMB) { - gba->bus |= cpu->prefetch[1] << 16; - } - - if (gba->springIRQ) { - ARMRaiseIRQ(cpu); - gba->springIRQ = 0; - } - testEvent = GBAVideoProcessEvents(&gba->video, cycles); if (testEvent < nextEvent) { nextEvent = testEvent;