From f06d22d6f01e657ebbc0c8ef082739cd468e47b5 Mon Sep 17 00:00:00 2001
From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
Date: Sun, 11 Feb 2024 02:09:18 +0000
Subject: Infra: Capitalisation Consistency (#6296)

* Rename Ryujinx.UI.Common

* Rename Ryujinx.UI.LocaleGenerator

* Update in Files

AboutWindow

* Configuration State

* Rename projects

* Ryujinx/UI

* Fix build

* Main remaining inconsistencies

* HLE.UI Namespace

* HLE.UI Files

* Namespace

* Ryujinx.UI.Common.Configuration.UI

* Ryujinx.UI.Common,Configuration.UI Files

* More instances
---
 src/Ryujinx.Ava/App.axaml.cs                       |   16 +-
 src/Ryujinx.Ava/AppHost.cs                         |   14 +-
 src/Ryujinx.Ava/Common/ApplicationHelper.cs        |    4 +-
 src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs      |    2 +-
 src/Ryujinx.Ava/Common/Locale/LocaleManager.cs     |    6 +-
 src/Ryujinx.Ava/Modules/Updater/Updater.cs         |    4 +-
 src/Ryujinx.Ava/Program.cs                         |    8 +-
 src/Ryujinx.Ava/Ryujinx.Ava.csproj                 |    6 +-
 src/Ryujinx.Ava/UI/Applet/AvaHostUIHandler.cs      |  204 ++
 src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs      |  204 --
 .../UI/Applet/AvaloniaDynamicTextInputHandler.cs   |    2 +-
 src/Ryujinx.Ava/UI/Applet/AvaloniaHostUITheme.cs   |   41 +
 src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs   |   41 -
 .../UI/Applet/ControllerAppletDialog.axaml.cs      |    4 +-
 src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml  |    2 +-
 src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml  |    2 +-
 .../UI/Applet/SwkbdAppletDialog.axaml.cs           |    2 +-
 .../UI/Controls/ApplicationContextMenu.axaml.cs    |    4 +-
 .../UI/Controls/ApplicationGridView.axaml.cs       |    2 +-
 .../UI/Controls/ApplicationListView.axaml.cs       |    2 +-
 src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml |    4 +-
 .../UI/Helpers/ApplicationOpenedEventArgs.cs       |    2 +-
 src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs  |    2 +-
 .../UI/Helpers/LocalizedNeverConverter.cs          |    2 +-
 src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs        |    4 +-
 src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs      |    4 +-
 .../UI/Models/Generic/LastPlayedSortComparer.cs    |    2 +-
 .../UI/Models/Generic/TimePlayedSortComparer.cs    |    2 +-
 src/Ryujinx.Ava/UI/Models/SaveModel.cs             |    4 +-
 src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs      |    4 +-
 .../UI/Renderer/EmbeddedWindowOpenGL.cs            |    4 +-
 src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs  |    2 +-
 .../UI/ViewModels/AboutWindowViewModel.cs          |   20 +-
 .../UI/ViewModels/AmiiboWindowViewModel.cs         |    4 +-
 .../UI/ViewModels/ControllerInputViewModel.cs      |   10 +-
 .../UI/ViewModels/MainWindowViewModel.cs           |   58 +-
 src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs |   12 +-
 .../UI/ViewModels/TitleUpdateViewModel.cs          |    2 +-
 .../UI/Views/Main/MainMenuBarView.axaml.cs         |    8 +-
 .../UI/Views/Main/MainStatusBarView.axaml.cs       |    2 +-
 .../UI/Views/Settings/SettingsHotkeysView.axaml    |    2 +-
 src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml       |    2 +-
 src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs    |    2 +-
 src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs   |    2 +-
 src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs    |    2 +-
 .../DownloadableContentManagerWindow.axaml.cs      |    2 +-
 src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs     |   46 +-
 .../UI/Windows/ModManagerWindow.axaml.cs           |    2 +-
 src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs      |    4 +-
 .../UI/Windows/TitleUpdateWindow.axaml.cs          |    2 +-
 .../Configuration/Hid/KeyboardHotkeys.cs           |    2 +-
 src/Ryujinx.Common/Logging/LogClass.cs             |    2 +-
 src/Ryujinx.HLE/HLEConfiguration.cs                |    8 +-
 .../HOS/Applets/Controller/ControllerApplet.cs     |    4 +-
 .../Applets/Controller/ControllerAppletUIArgs.cs   |   14 +
 .../Applets/Controller/ControllerAppletUiArgs.cs   |   14 -
 src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs   |    8 +-
 src/Ryujinx.HLE/HOS/Applets/IApplet.cs             |    2 +-
 .../SoftwareKeyboard/SoftwareKeyboardApplet.cs     |   16 +-
 .../SoftwareKeyboard/SoftwareKeyboardRenderer.cs   |   12 +-
 .../SoftwareKeyboardRendererBase.cs                |    8 +-
 .../SoftwareKeyboard/SoftwareKeyboardUIArgs.cs     |   16 +
 .../SoftwareKeyboard/SoftwareKeyboardUIState.cs    |   22 +
 .../SoftwareKeyboard/SoftwareKeyboardUiArgs.cs     |   16 -
 .../SoftwareKeyboard/SoftwareKeyboardUiState.cs    |   22 -
 .../ApplicationProxy/IApplicationFunctions.cs      |    4 +-
 .../Vi/RootService/IApplicationDisplayService.cs   |    2 +-
 src/Ryujinx.HLE/Switch.cs                          |    6 +-
 src/Ryujinx.HLE/UI/DynamicTextChangedHandler.cs    |    4 +
 src/Ryujinx.HLE/UI/IDynamicTextInputHandler.cs     |   16 +
 src/Ryujinx.HLE/UI/IHostUIHandler.cs               |   51 +
 src/Ryujinx.HLE/UI/IHostUITheme.cs                 |   13 +
 src/Ryujinx.HLE/UI/Input/NpadButtonHandler.cs      |    6 +
 src/Ryujinx.HLE/UI/Input/NpadReader.cs             |  140 +
 src/Ryujinx.HLE/UI/KeyPressedHandler.cs            |    6 +
 src/Ryujinx.HLE/UI/KeyReleasedHandler.cs           |    6 +
 src/Ryujinx.HLE/UI/RenderingSurfaceInfo.cs         |   45 +
 src/Ryujinx.HLE/UI/ThemeColor.cs                   |   18 +
 src/Ryujinx.HLE/Ui/DynamicTextChangedHandler.cs    |    4 -
 src/Ryujinx.HLE/Ui/IDynamicTextInputHandler.cs     |   16 -
 src/Ryujinx.HLE/Ui/IHostUiHandler.cs               |   51 -
 src/Ryujinx.HLE/Ui/IHostUiTheme.cs                 |   13 -
 src/Ryujinx.HLE/Ui/Input/NpadButtonHandler.cs      |    6 -
 src/Ryujinx.HLE/Ui/Input/NpadReader.cs             |  140 -
 src/Ryujinx.HLE/Ui/KeyPressedHandler.cs            |    6 -
 src/Ryujinx.HLE/Ui/KeyReleasedHandler.cs           |    6 -
 src/Ryujinx.HLE/Ui/RenderingSurfaceInfo.cs         |   45 -
 src/Ryujinx.HLE/Ui/ThemeColor.cs                   |   18 -
 .../HeadlessDynamicTextInputHandler.cs             |    2 +-
 src/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs   |    4 +-
 src/Ryujinx.Headless.SDL2/WindowBase.cs            |   12 +-
 .../App/ApplicationAddedEventArgs.cs               |    9 +
 .../App/ApplicationCountUpdatedEventArgs.cs        |   10 +
 src/Ryujinx.UI.Common/App/ApplicationData.cs       |  158 +
 .../App/ApplicationJsonSerializerContext.cs        |   10 +
 src/Ryujinx.UI.Common/App/ApplicationLibrary.cs    |  930 ++++++
 src/Ryujinx.UI.Common/App/ApplicationMetadata.cs   |   51 +
 .../Configuration/AudioBackend.cs                  |   14 +
 .../Configuration/ConfigurationFileFormat.cs       |  409 +++
 .../ConfigurationFileFormatSettings.cs             |    9 +
 .../ConfigurationJsonSerializerContext.cs          |   10 +
 .../Configuration/ConfigurationState.cs            | 1562 ++++++++++
 src/Ryujinx.UI.Common/Configuration/FileTypes.cs   |   12 +
 .../Configuration/LoggerModule.cs                  |  113 +
 .../Configuration/System/Language.cs               |   28 +
 .../Configuration/System/Region.cs                 |   17 +
 .../Configuration/UI/ColumnSort.cs                 |    8 +
 .../Configuration/UI/GuiColumns.cs                 |   16 +
 .../Configuration/UI/ShownFileTypes.cs             |   12 +
 .../Configuration/UI/WindowStartup.cs              |   11 +
 src/Ryujinx.UI.Common/DiscordIntegrationModule.cs  |   98 +
 .../Extensions/FileTypeExtensions.cs               |   25 +
 src/Ryujinx.UI.Common/Helper/CommandLineState.cs   |   99 +
 src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs      |   50 +
 .../Helper/FileAssociationHelper.cs                |  202 ++
 src/Ryujinx.UI.Common/Helper/LinuxHelper.cs        |   62 +
 src/Ryujinx.UI.Common/Helper/ObjectiveC.cs         |  160 +
 src/Ryujinx.UI.Common/Helper/OpenHelper.cs         |  112 +
 src/Ryujinx.UI.Common/Helper/SetupValidator.cs     |  114 +
 src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs     |  162 +
 src/Ryujinx.UI.Common/Helper/TitleHelper.cs        |   30 +
 src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs   |  219 ++
 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs   |   67 +
 .../Models/Amiibo/AmiiboApiGamesSwitch.cs          |   15 +
 .../Models/Amiibo/AmiiboApiUsage.cs                |   12 +
 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs  |   14 +
 .../Models/Amiibo/AmiiboJsonSerializerContext.cs   |    9 +
 .../Github/GithubReleaseAssetJsonResponse.cs       |    9 +
 .../Models/Github/GithubReleasesJsonResponse.cs    |   10 +
 .../Github/GithubReleasesJsonSerializerContext.cs  |    9 +
 .../Resources/Controller_JoyConLeft.svg            |    1 +
 .../Resources/Controller_JoyConPair.svg            |    1 +
 .../Resources/Controller_JoyConRight.svg           |    1 +
 .../Resources/Controller_ProCon.svg                |  132 +
 src/Ryujinx.UI.Common/Resources/Icon_NCA.png       |  Bin 0 -> 10190 bytes
 src/Ryujinx.UI.Common/Resources/Icon_NRO.png       |  Bin 0 -> 10254 bytes
 src/Ryujinx.UI.Common/Resources/Icon_NSO.png       |  Bin 0 -> 10354 bytes
 src/Ryujinx.UI.Common/Resources/Icon_NSP.png       |  Bin 0 -> 9899 bytes
 src/Ryujinx.UI.Common/Resources/Icon_XCI.png       |  Bin 0 -> 9809 bytes
 src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png    |  Bin 0 -> 10573 bytes
 .../Resources/Logo_Discord_Dark.png                |  Bin 0 -> 9835 bytes
 .../Resources/Logo_Discord_Light.png               |  Bin 0 -> 10765 bytes
 .../Resources/Logo_GitHub_Dark.png                 |  Bin 0 -> 4837 bytes
 .../Resources/Logo_GitHub_Light.png                |  Bin 0 -> 5166 bytes
 .../Resources/Logo_Patreon_Dark.png                |  Bin 0 -> 52210 bytes
 .../Resources/Logo_Patreon_Light.png               |  Bin 0 -> 29395 bytes
 src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png   |  Bin 0 -> 52972 bytes
 .../Resources/Logo_Twitter_Dark.png                |  Bin 0 -> 18385 bytes
 .../Resources/Logo_Twitter_Light.png               |  Bin 0 -> 19901 bytes
 src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj     |   68 +
 .../SystemInfo/LinuxSystemInfo.cs                  |   85 +
 .../SystemInfo/MacOSSystemInfo.cs                  |  164 +
 src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs     |   79 +
 .../SystemInfo/WindowsSystemInfo.cs                |   87 +
 src/Ryujinx.UI.Common/UserError.cs                 |   39 +
 src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs  |   33 +
 .../Ryujinx.UI.LocaleGenerator.csproj              |   18 +
 .../App/ApplicationAddedEventArgs.cs               |    9 -
 .../App/ApplicationCountUpdatedEventArgs.cs        |   10 -
 src/Ryujinx.Ui.Common/App/ApplicationData.cs       |  158 -
 .../App/ApplicationJsonSerializerContext.cs        |   10 -
 src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs    |  930 ------
 src/Ryujinx.Ui.Common/App/ApplicationMetadata.cs   |   51 -
 .../Configuration/AudioBackend.cs                  |   14 -
 .../Configuration/ConfigurationFileFormat.cs       |  409 ---
 .../ConfigurationFileFormatSettings.cs             |    9 -
 .../ConfigurationJsonSerializerContext.cs          |   10 -
 .../Configuration/ConfigurationState.cs            | 1562 ----------
 src/Ryujinx.Ui.Common/Configuration/FileTypes.cs   |   12 -
 .../Configuration/LoggerModule.cs                  |  113 -
 .../Configuration/System/Language.cs               |   28 -
 .../Configuration/System/Region.cs                 |   17 -
 .../Configuration/Ui/ColumnSort.cs                 |    8 -
 .../Configuration/Ui/GuiColumns.cs                 |   16 -
 .../Configuration/Ui/ShownFileTypes.cs             |   12 -
 .../Configuration/Ui/WindowStartup.cs              |   11 -
 src/Ryujinx.Ui.Common/DiscordIntegrationModule.cs  |   98 -
 .../Extensions/FileTypeExtensions.cs               |   25 -
 src/Ryujinx.Ui.Common/Helper/CommandLineState.cs   |   99 -
 src/Ryujinx.Ui.Common/Helper/ConsoleHelper.cs      |   50 -
 .../Helper/FileAssociationHelper.cs                |  202 --
 src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs        |   62 -
 src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs         |  160 -
 src/Ryujinx.Ui.Common/Helper/OpenHelper.cs         |  112 -
 src/Ryujinx.Ui.Common/Helper/SetupValidator.cs     |  114 -
 src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs     |  162 -
 src/Ryujinx.Ui.Common/Helper/TitleHelper.cs        |   30 -
 src/Ryujinx.Ui.Common/Helper/ValueFormatUtils.cs   |  219 --
 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApi.cs   |   67 -
 .../Models/Amiibo/AmiiboApiGamesSwitch.cs          |   15 -
 .../Models/Amiibo/AmiiboApiUsage.cs                |   12 -
 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJson.cs  |   14 -
 .../Models/Amiibo/AmiiboJsonSerializerContext.cs   |    9 -
 .../Github/GithubReleaseAssetJsonResponse.cs       |    9 -
 .../Models/Github/GithubReleasesJsonResponse.cs    |   10 -
 .../Github/GithubReleasesJsonSerializerContext.cs  |    9 -
 .../Resources/Controller_JoyConLeft.svg            |    1 -
 .../Resources/Controller_JoyConPair.svg            |    1 -
 .../Resources/Controller_JoyConRight.svg           |    1 -
 .../Resources/Controller_ProCon.svg                |  132 -
 src/Ryujinx.Ui.Common/Resources/Icon_NCA.png       |  Bin 10190 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Icon_NRO.png       |  Bin 10254 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Icon_NSO.png       |  Bin 10354 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Icon_NSP.png       |  Bin 9899 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Icon_XCI.png       |  Bin 9809 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Logo_Amiibo.png    |  Bin 10573 -> 0 bytes
 .../Resources/Logo_Discord_Dark.png                |  Bin 9835 -> 0 bytes
 .../Resources/Logo_Discord_Light.png               |  Bin 10765 -> 0 bytes
 .../Resources/Logo_GitHub_Dark.png                 |  Bin 4837 -> 0 bytes
 .../Resources/Logo_GitHub_Light.png                |  Bin 5166 -> 0 bytes
 .../Resources/Logo_Patreon_Dark.png                |  Bin 52210 -> 0 bytes
 .../Resources/Logo_Patreon_Light.png               |  Bin 29395 -> 0 bytes
 src/Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png   |  Bin 52972 -> 0 bytes
 .../Resources/Logo_Twitter_Dark.png                |  Bin 18385 -> 0 bytes
 .../Resources/Logo_Twitter_Light.png               |  Bin 19901 -> 0 bytes
 src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj     |   68 -
 .../SystemInfo/LinuxSystemInfo.cs                  |   85 -
 .../SystemInfo/MacOSSystemInfo.cs                  |  164 -
 src/Ryujinx.Ui.Common/SystemInfo/SystemInfo.cs     |   79 -
 .../SystemInfo/WindowsSystemInfo.cs                |   87 -
 src/Ryujinx.Ui.Common/UserError.cs                 |   39 -
 src/Ryujinx.Ui.LocaleGenerator/LocaleGenerator.cs  |   33 -
 .../Ryujinx.Ui.LocaleGenerator.csproj              |   18 -
 src/Ryujinx/Modules/Updater/UpdateDialog.cs        |    8 +-
 src/Ryujinx/Modules/Updater/Updater.cs             |    6 +-
 src/Ryujinx/Program.cs                             |   12 +-
 src/Ryujinx/Ryujinx.csproj                         |   30 +-
 src/Ryujinx/UI/Applet/ErrorAppletDialog.cs         |   31 +
 .../UI/Applet/GtkDynamicTextInputHandler.cs        |  108 +
 src/Ryujinx/UI/Applet/GtkHostUIHandler.cs          |  200 ++
 src/Ryujinx/UI/Applet/GtkHostUITheme.cs            |   90 +
 src/Ryujinx/UI/Applet/SwkbdAppletDialog.cs         |  127 +
 src/Ryujinx/UI/Helper/MetalHelper.cs               |  135 +
 src/Ryujinx/UI/Helper/SortHelper.cs                |   33 +
 src/Ryujinx/UI/Helper/ThemeHelper.cs               |   36 +
 src/Ryujinx/UI/MainWindow.cs                       | 1941 ++++++++++++
 src/Ryujinx/UI/MainWindow.glade                    | 1006 ++++++
 src/Ryujinx/UI/OpenGLRenderer.cs                   |  142 +
 src/Ryujinx/UI/OpenToolkitBindingsContext.cs       |   20 +
 src/Ryujinx/UI/RendererWidgetBase.cs               |  803 +++++
 src/Ryujinx/UI/SPBOpenGLContext.cs                 |   49 +
 src/Ryujinx/UI/StatusUpdatedEventArgs.cs           |   28 +
 src/Ryujinx/UI/VulkanRenderer.cs                   |   93 +
 .../UI/Widgets/GameTableContextMenu.Designer.cs    |  233 ++
 src/Ryujinx/UI/Widgets/GameTableContextMenu.cs     |  644 ++++
 src/Ryujinx/UI/Widgets/GtkDialog.cs                |  114 +
 src/Ryujinx/UI/Widgets/GtkInputDialog.cs           |   37 +
 src/Ryujinx/UI/Widgets/ProfileDialog.cs            |   57 +
 src/Ryujinx/UI/Widgets/ProfileDialog.glade         |  124 +
 src/Ryujinx/UI/Widgets/RawInputToTextEntry.cs      |   27 +
 src/Ryujinx/UI/Widgets/UserErrorDialog.cs          |  123 +
 src/Ryujinx/UI/Windows/AboutWindow.Designer.cs     |  511 ++++
 src/Ryujinx/UI/Windows/AboutWindow.cs              |   85 +
 src/Ryujinx/UI/Windows/AmiiboWindow.Designer.cs    |  190 ++
 src/Ryujinx/UI/Windows/AmiiboWindow.cs             |  438 +++
 src/Ryujinx/UI/Windows/AvatarWindow.cs             |  291 ++
 src/Ryujinx/UI/Windows/CheatWindow.cs              |  156 +
 src/Ryujinx/UI/Windows/CheatWindow.glade           |  150 +
 src/Ryujinx/UI/Windows/ControllerWindow.cs         | 1230 ++++++++
 src/Ryujinx/UI/Windows/ControllerWindow.glade      | 2241 ++++++++++++++
 src/Ryujinx/UI/Windows/DlcWindow.cs                |  280 ++
 src/Ryujinx/UI/Windows/DlcWindow.glade             |  202 ++
 src/Ryujinx/UI/Windows/SettingsWindow.cs           |  847 +++++
 src/Ryujinx/UI/Windows/SettingsWindow.glade        | 3221 ++++++++++++++++++++
 src/Ryujinx/UI/Windows/TitleUpdateWindow.cs        |  206 ++
 src/Ryujinx/UI/Windows/TitleUpdateWindow.glade     |  214 ++
 .../Windows/UserProfilesManagerWindow.Designer.cs  |  255 ++
 .../UI/Windows/UserProfilesManagerWindow.cs        |  328 ++
 src/Ryujinx/Ui/Applet/ErrorAppletDialog.cs         |   31 -
 .../Ui/Applet/GtkDynamicTextInputHandler.cs        |  108 -
 src/Ryujinx/Ui/Applet/GtkHostUiHandler.cs          |  200 --
 src/Ryujinx/Ui/Applet/GtkHostUiTheme.cs            |   90 -
 src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs         |  127 -
 src/Ryujinx/Ui/Helper/MetalHelper.cs               |  135 -
 src/Ryujinx/Ui/Helper/SortHelper.cs                |   33 -
 src/Ryujinx/Ui/Helper/ThemeHelper.cs               |   36 -
 src/Ryujinx/Ui/MainWindow.cs                       | 1941 ------------
 src/Ryujinx/Ui/MainWindow.glade                    | 1006 ------
 src/Ryujinx/Ui/OpenGLRenderer.cs                   |  142 -
 src/Ryujinx/Ui/OpenToolkitBindingsContext.cs       |   20 -
 src/Ryujinx/Ui/RendererWidgetBase.cs               |  803 -----
 src/Ryujinx/Ui/SPBOpenGLContext.cs                 |   49 -
 src/Ryujinx/Ui/StatusUpdatedEventArgs.cs           |   28 -
 src/Ryujinx/Ui/VulkanRenderer.cs                   |   93 -
 .../Ui/Widgets/GameTableContextMenu.Designer.cs    |  233 --
 src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs     |  644 ----
 src/Ryujinx/Ui/Widgets/GtkDialog.cs                |  114 -
 src/Ryujinx/Ui/Widgets/GtkInputDialog.cs           |   37 -
 src/Ryujinx/Ui/Widgets/ProfileDialog.cs            |   57 -
 src/Ryujinx/Ui/Widgets/ProfileDialog.glade         |  124 -
 src/Ryujinx/Ui/Widgets/RawInputToTextEntry.cs      |   27 -
 src/Ryujinx/Ui/Widgets/UserErrorDialog.cs          |  123 -
 src/Ryujinx/Ui/Windows/AboutWindow.Designer.cs     |  511 ----
 src/Ryujinx/Ui/Windows/AboutWindow.cs              |   85 -
 src/Ryujinx/Ui/Windows/AmiiboWindow.Designer.cs    |  190 --
 src/Ryujinx/Ui/Windows/AmiiboWindow.cs             |  438 ---
 src/Ryujinx/Ui/Windows/AvatarWindow.cs             |  291 --
 src/Ryujinx/Ui/Windows/CheatWindow.cs              |  156 -
 src/Ryujinx/Ui/Windows/CheatWindow.glade           |  150 -
 src/Ryujinx/Ui/Windows/ControllerWindow.cs         | 1230 --------
 src/Ryujinx/Ui/Windows/ControllerWindow.glade      | 2241 --------------
 src/Ryujinx/Ui/Windows/DlcWindow.cs                |  280 --
 src/Ryujinx/Ui/Windows/DlcWindow.glade             |  202 --
 src/Ryujinx/Ui/Windows/SettingsWindow.cs           |  847 -----
 src/Ryujinx/Ui/Windows/SettingsWindow.glade        | 3221 --------------------
 src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs        |  206 --
 src/Ryujinx/Ui/Windows/TitleUpdateWindow.glade     |  214 --
 .../Windows/UserProfilesManagerWindow.Designer.cs  |  255 --
 .../Ui/Windows/UserProfilesManagerWindow.cs        |  328 --
 309 files changed, 23446 insertions(+), 23446 deletions(-)
 create mode 100644 src/Ryujinx.Ava/UI/Applet/AvaHostUIHandler.cs
 delete mode 100644 src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
 create mode 100644 src/Ryujinx.Ava/UI/Applet/AvaloniaHostUITheme.cs
 delete mode 100644 src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
 create mode 100644 src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUIArgs.cs
 delete mode 100644 src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUiArgs.cs
 create mode 100644 src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIArgs.cs
 create mode 100644 src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIState.cs
 delete mode 100644 src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs
 delete mode 100644 src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiState.cs
 create mode 100644 src/Ryujinx.HLE/UI/DynamicTextChangedHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/IDynamicTextInputHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/IHostUIHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/IHostUITheme.cs
 create mode 100644 src/Ryujinx.HLE/UI/Input/NpadButtonHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/Input/NpadReader.cs
 create mode 100644 src/Ryujinx.HLE/UI/KeyPressedHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/KeyReleasedHandler.cs
 create mode 100644 src/Ryujinx.HLE/UI/RenderingSurfaceInfo.cs
 create mode 100644 src/Ryujinx.HLE/UI/ThemeColor.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/DynamicTextChangedHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/IDynamicTextInputHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/IHostUiHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/IHostUiTheme.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/Input/NpadButtonHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/Input/NpadReader.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/KeyPressedHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/KeyReleasedHandler.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/RenderingSurfaceInfo.cs
 delete mode 100644 src/Ryujinx.HLE/Ui/ThemeColor.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationData.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationLibrary.cs
 create mode 100644 src/Ryujinx.UI.Common/App/ApplicationMetadata.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/AudioBackend.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/FileTypes.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/LoggerModule.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/System/Language.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/System/Region.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs
 create mode 100644 src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs
 create mode 100644 src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
 create mode 100644 src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/CommandLineState.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/LinuxHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/ObjectiveC.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/OpenHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/SetupValidator.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/TitleHelper.cs
 create mode 100644 src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs
 create mode 100644 src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
 create mode 100644 src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg
 create mode 100644 src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg
 create mode 100644 src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg
 create mode 100644 src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg
 create mode 100644 src/Ryujinx.UI.Common/Resources/Icon_NCA.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Icon_NRO.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Icon_NSO.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Icon_NSP.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Icon_XCI.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png
 create mode 100644 src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png
 create mode 100644 src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj
 create mode 100644 src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs
 create mode 100644 src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs
 create mode 100644 src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs
 create mode 100644 src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs
 create mode 100644 src/Ryujinx.UI.Common/UserError.cs
 create mode 100644 src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs
 create mode 100644 src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationAddedEventArgs.cs
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationCountUpdatedEventArgs.cs
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationData.cs
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationJsonSerializerContext.cs
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
 delete mode 100644 src/Ryujinx.Ui.Common/App/ApplicationMetadata.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/AudioBackend.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormatSettings.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/ConfigurationJsonSerializerContext.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/FileTypes.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/System/Language.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/System/Region.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/Ui/ColumnSort.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/Ui/GuiColumns.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Configuration/Ui/WindowStartup.cs
 delete mode 100644 src/Ryujinx.Ui.Common/DiscordIntegrationModule.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/CommandLineState.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/ConsoleHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/OpenHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/SetupValidator.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/TitleHelper.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Helper/ValueFormatUtils.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApi.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiUsage.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJson.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonResponse.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Controller_ProCon.svg
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Icon_NCA.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Icon_NRO.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Icon_NSO.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Icon_NSP.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Icon_XCI.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Amiibo.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Discord_Dark.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Discord_Light.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Dark.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Light.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Dark.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Light.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Dark.png
 delete mode 100644 src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Light.png
 delete mode 100644 src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
 delete mode 100644 src/Ryujinx.Ui.Common/SystemInfo/LinuxSystemInfo.cs
 delete mode 100644 src/Ryujinx.Ui.Common/SystemInfo/MacOSSystemInfo.cs
 delete mode 100644 src/Ryujinx.Ui.Common/SystemInfo/SystemInfo.cs
 delete mode 100644 src/Ryujinx.Ui.Common/SystemInfo/WindowsSystemInfo.cs
 delete mode 100644 src/Ryujinx.Ui.Common/UserError.cs
 delete mode 100644 src/Ryujinx.Ui.LocaleGenerator/LocaleGenerator.cs
 delete mode 100644 src/Ryujinx.Ui.LocaleGenerator/Ryujinx.Ui.LocaleGenerator.csproj
 create mode 100644 src/Ryujinx/UI/Applet/ErrorAppletDialog.cs
 create mode 100644 src/Ryujinx/UI/Applet/GtkDynamicTextInputHandler.cs
 create mode 100644 src/Ryujinx/UI/Applet/GtkHostUIHandler.cs
 create mode 100644 src/Ryujinx/UI/Applet/GtkHostUITheme.cs
 create mode 100644 src/Ryujinx/UI/Applet/SwkbdAppletDialog.cs
 create mode 100644 src/Ryujinx/UI/Helper/MetalHelper.cs
 create mode 100644 src/Ryujinx/UI/Helper/SortHelper.cs
 create mode 100644 src/Ryujinx/UI/Helper/ThemeHelper.cs
 create mode 100644 src/Ryujinx/UI/MainWindow.cs
 create mode 100644 src/Ryujinx/UI/MainWindow.glade
 create mode 100644 src/Ryujinx/UI/OpenGLRenderer.cs
 create mode 100644 src/Ryujinx/UI/OpenToolkitBindingsContext.cs
 create mode 100644 src/Ryujinx/UI/RendererWidgetBase.cs
 create mode 100644 src/Ryujinx/UI/SPBOpenGLContext.cs
 create mode 100644 src/Ryujinx/UI/StatusUpdatedEventArgs.cs
 create mode 100644 src/Ryujinx/UI/VulkanRenderer.cs
 create mode 100644 src/Ryujinx/UI/Widgets/GameTableContextMenu.Designer.cs
 create mode 100644 src/Ryujinx/UI/Widgets/GameTableContextMenu.cs
 create mode 100644 src/Ryujinx/UI/Widgets/GtkDialog.cs
 create mode 100644 src/Ryujinx/UI/Widgets/GtkInputDialog.cs
 create mode 100644 src/Ryujinx/UI/Widgets/ProfileDialog.cs
 create mode 100644 src/Ryujinx/UI/Widgets/ProfileDialog.glade
 create mode 100644 src/Ryujinx/UI/Widgets/RawInputToTextEntry.cs
 create mode 100644 src/Ryujinx/UI/Widgets/UserErrorDialog.cs
 create mode 100644 src/Ryujinx/UI/Windows/AboutWindow.Designer.cs
 create mode 100644 src/Ryujinx/UI/Windows/AboutWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/AmiiboWindow.Designer.cs
 create mode 100644 src/Ryujinx/UI/Windows/AmiiboWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/AvatarWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/CheatWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/CheatWindow.glade
 create mode 100644 src/Ryujinx/UI/Windows/ControllerWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/ControllerWindow.glade
 create mode 100644 src/Ryujinx/UI/Windows/DlcWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/DlcWindow.glade
 create mode 100644 src/Ryujinx/UI/Windows/SettingsWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/SettingsWindow.glade
 create mode 100644 src/Ryujinx/UI/Windows/TitleUpdateWindow.cs
 create mode 100644 src/Ryujinx/UI/Windows/TitleUpdateWindow.glade
 create mode 100644 src/Ryujinx/UI/Windows/UserProfilesManagerWindow.Designer.cs
 create mode 100644 src/Ryujinx/UI/Windows/UserProfilesManagerWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Applet/ErrorAppletDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Applet/GtkDynamicTextInputHandler.cs
 delete mode 100644 src/Ryujinx/Ui/Applet/GtkHostUiHandler.cs
 delete mode 100644 src/Ryujinx/Ui/Applet/GtkHostUiTheme.cs
 delete mode 100644 src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Helper/MetalHelper.cs
 delete mode 100644 src/Ryujinx/Ui/Helper/SortHelper.cs
 delete mode 100644 src/Ryujinx/Ui/Helper/ThemeHelper.cs
 delete mode 100644 src/Ryujinx/Ui/MainWindow.cs
 delete mode 100644 src/Ryujinx/Ui/MainWindow.glade
 delete mode 100644 src/Ryujinx/Ui/OpenGLRenderer.cs
 delete mode 100644 src/Ryujinx/Ui/OpenToolkitBindingsContext.cs
 delete mode 100644 src/Ryujinx/Ui/RendererWidgetBase.cs
 delete mode 100644 src/Ryujinx/Ui/SPBOpenGLContext.cs
 delete mode 100644 src/Ryujinx/Ui/StatusUpdatedEventArgs.cs
 delete mode 100644 src/Ryujinx/Ui/VulkanRenderer.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/GameTableContextMenu.Designer.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/GtkDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/GtkInputDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/ProfileDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/ProfileDialog.glade
 delete mode 100644 src/Ryujinx/Ui/Widgets/RawInputToTextEntry.cs
 delete mode 100644 src/Ryujinx/Ui/Widgets/UserErrorDialog.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/AboutWindow.Designer.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/AboutWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/AmiiboWindow.Designer.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/AmiiboWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/AvatarWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/CheatWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/CheatWindow.glade
 delete mode 100644 src/Ryujinx/Ui/Windows/ControllerWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/ControllerWindow.glade
 delete mode 100644 src/Ryujinx/Ui/Windows/DlcWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/DlcWindow.glade
 delete mode 100644 src/Ryujinx/Ui/Windows/SettingsWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/SettingsWindow.glade
 delete mode 100644 src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/TitleUpdateWindow.glade
 delete mode 100644 src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.Designer.cs
 delete mode 100644 src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.cs

(limited to 'src')

diff --git a/src/Ryujinx.Ava/App.axaml.cs b/src/Ryujinx.Ava/App.axaml.cs
index 54e61c67..387a6dc1 100644
--- a/src/Ryujinx.Ava/App.axaml.cs
+++ b/src/Ryujinx.Ava/App.axaml.cs
@@ -8,8 +8,8 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Diagnostics;
 
@@ -42,9 +42,9 @@ namespace Ryujinx.Ava
             {
                 ApplyConfiguredTheme();
 
-                ConfigurationState.Instance.Ui.BaseStyle.Event += ThemeChanged_Event;
-                ConfigurationState.Instance.Ui.CustomThemePath.Event += ThemeChanged_Event;
-                ConfigurationState.Instance.Ui.EnableCustomTheme.Event += CustomThemeChanged_Event;
+                ConfigurationState.Instance.UI.BaseStyle.Event += ThemeChanged_Event;
+                ConfigurationState.Instance.UI.CustomThemePath.Event += ThemeChanged_Event;
+                ConfigurationState.Instance.UI.EnableCustomTheme.Event += CustomThemeChanged_Event;
             }
         }
 
@@ -88,13 +88,13 @@ namespace Ryujinx.Ava
         {
             try
             {
-                string baseStyle = ConfigurationState.Instance.Ui.BaseStyle;
+                string baseStyle = ConfigurationState.Instance.UI.BaseStyle;
 
                 if (string.IsNullOrWhiteSpace(baseStyle))
                 {
-                    ConfigurationState.Instance.Ui.BaseStyle.Value = "Dark";
+                    ConfigurationState.Instance.UI.BaseStyle.Value = "Dark";
 
-                    baseStyle = ConfigurationState.Instance.Ui.BaseStyle;
+                    baseStyle = ConfigurationState.Instance.UI.BaseStyle;
                 }
 
                 RequestedThemeVariant = baseStyle switch
diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs
index 696a4046..04cec957 100644
--- a/src/Ryujinx.Ava/AppHost.cs
+++ b/src/Ryujinx.Ava/AppHost.cs
@@ -34,10 +34,10 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.HLE.HOS.SystemState;
 using Ryujinx.Input;
 using Ryujinx.Input.HLE;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using Silk.NET.Vulkan;
 using SixLabors.ImageSharp;
 using SixLabors.ImageSharp.Formats.Png;
@@ -1070,7 +1070,7 @@ namespace Ryujinx.Ava
                         case KeyboardHotkeyState.Screenshot:
                             ScreenshotRequested = true;
                             break;
-                        case KeyboardHotkeyState.ShowUi:
+                        case KeyboardHotkeyState.ShowUI:
                             _viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar;
                             break;
                         case KeyboardHotkeyState.Pause:
@@ -1160,9 +1160,9 @@ namespace Ryujinx.Ava
             {
                 state = KeyboardHotkeyState.Screenshot;
             }
-            else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
+            else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI))
             {
-                state = KeyboardHotkeyState.ShowUi;
+                state = KeyboardHotkeyState.ShowUI;
             }
             else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
             {
diff --git a/src/Ryujinx.Ava/Common/ApplicationHelper.cs b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
index 91ca8f4d..622a6a02 100644
--- a/src/Ryujinx.Ava/Common/ApplicationHelper.cs
+++ b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
@@ -18,8 +18,8 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Buffers;
 using System.IO;
diff --git a/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs b/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs
index b2401640..6e492098 100644
--- a/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs
+++ b/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs
@@ -5,7 +5,7 @@ namespace Ryujinx.Ava.Common
         None,
         ToggleVSync,
         Screenshot,
-        ShowUi,
+        ShowUI,
         Pause,
         ToggleMute,
         ResScaleUp,
diff --git a/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs b/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs
index 0e613838..b2f3e7ab 100644
--- a/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs
+++ b/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs
@@ -1,7 +1,7 @@
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Common;
 using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -38,9 +38,9 @@ namespace Ryujinx.Ava.Common.Locale
             // If the view is loaded with the UI Previewer detached, then override it with the saved one or default.
             if (Program.PreviewerDetached)
             {
-                if (!string.IsNullOrEmpty(ConfigurationState.Instance.Ui.LanguageCode.Value))
+                if (!string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value))
                 {
-                    localeLanguageCode = ConfigurationState.Instance.Ui.LanguageCode.Value;
+                    localeLanguageCode = ConfigurationState.Instance.UI.LanguageCode.Value;
                 }
                 else
                 {
diff --git a/src/Ryujinx.Ava/Modules/Updater/Updater.cs b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
index ad33b101..bd211fa5 100644
--- a/src/Ryujinx.Ava/Modules/Updater/Updater.cs
+++ b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
@@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Common.Models.Github;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Common.Models.Github;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
diff --git a/src/Ryujinx.Ava/Program.cs b/src/Ryujinx.Ava/Program.cs
index d85749ef..7751bb52 100644
--- a/src/Ryujinx.Ava/Program.cs
+++ b/src/Ryujinx.Ava/Program.cs
@@ -9,10 +9,10 @@ using Ryujinx.Common.Logging;
 using Ryujinx.Common.SystemInterop;
 using Ryujinx.Modules;
 using Ryujinx.SDL2.Common;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Common.SystemInfo;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Common.SystemInfo;
 using System;
 using System.IO;
 using System.Runtime.InteropServices;
diff --git a/src/Ryujinx.Ava/Ryujinx.Ava.csproj b/src/Ryujinx.Ava/Ryujinx.Ava.csproj
index 5665178a..91c2744f 100644
--- a/src/Ryujinx.Ava/Ryujinx.Ava.csproj
+++ b/src/Ryujinx.Ava/Ryujinx.Ava.csproj
@@ -73,8 +73,8 @@
     <ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
     <ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
     <ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
-    <ProjectReference Include="..\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj" />
-    <ProjectReference Include="..\Ryujinx.Ui.LocaleGenerator\Ryujinx.Ui.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
+    <ProjectReference Include="..\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj" />
+    <ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
   </ItemGroup>
 
   <ItemGroup>
@@ -103,7 +103,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <AvaloniaResource Include="Ui\**\*.xaml">
+    <AvaloniaResource Include="UI\**\*.xaml">
       <SubType>Designer</SubType>
     </AvaloniaResource>
     <AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaHostUIHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaHostUIHandler.cs
new file mode 100644
index 00000000..4bcc35a7
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/Applet/AvaHostUIHandler.cs
@@ -0,0 +1,204 @@
+using Avalonia.Controls;
+using Avalonia.Threading;
+using FluentAvalonia.UI.Controls;
+using Ryujinx.Ava.Common.Locale;
+using Ryujinx.Ava.UI.Controls;
+using Ryujinx.Ava.UI.Helpers;
+using Ryujinx.Ava.UI.Windows;
+using Ryujinx.HLE;
+using Ryujinx.HLE.HOS.Applets;
+using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
+using Ryujinx.HLE.UI;
+using System;
+using System.Threading;
+
+namespace Ryujinx.Ava.UI.Applet
+{
+    internal class AvaHostUIHandler : IHostUIHandler
+    {
+        private readonly MainWindow _parent;
+
+        public IHostUITheme HostUITheme { get; }
+
+        public AvaHostUIHandler(MainWindow parent)
+        {
+            _parent = parent;
+
+            HostUITheme = new AvaloniaHostUITheme(parent);
+        }
+
+        public bool DisplayMessageDialog(ControllerAppletUIArgs args)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool okPressed = false;
+
+            Dispatcher.UIThread.InvokeAsync(async () =>
+            {
+                var response = await ControllerAppletDialog.ShowControllerAppletDialog(_parent, args);
+                if (response == UserResult.Ok)
+                {
+                    okPressed = true;
+                }
+
+                dialogCloseEvent.Set();
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            return okPressed;
+        }
+
+        public bool DisplayMessageDialog(string title, string message)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool okPressed = false;
+
+            Dispatcher.UIThread.InvokeAsync(async () =>
+            {
+                try
+                {
+                    ManualResetEvent deferEvent = new(false);
+
+                    bool opened = false;
+
+                    UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
+                       title,
+                       message,
+                       "",
+                       LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
+                       "",
+                       LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
+                       (int)Symbol.Important,
+                       deferEvent,
+                       async window =>
+                       {
+                           if (opened)
+                           {
+                               return;
+                           }
+
+                           opened = true;
+
+                           _parent.SettingsWindow = new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
+
+                           await _parent.SettingsWindow.ShowDialog(window);
+
+                           _parent.SettingsWindow = null;
+
+                           opened = false;
+                       });
+
+                    if (response == UserResult.Ok)
+                    {
+                        okPressed = true;
+                    }
+
+                    dialogCloseEvent.Set();
+                }
+                catch (Exception ex)
+                {
+                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageDialogErrorExceptionMessage, ex));
+
+                    dialogCloseEvent.Set();
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            return okPressed;
+        }
+
+        public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool okPressed = false;
+            bool error = false;
+            string inputText = args.InitialText ?? "";
+
+            Dispatcher.UIThread.InvokeAsync(async () =>
+            {
+                try
+                {
+                    var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
+
+                    if (response.Result == UserResult.Ok)
+                    {
+                        inputText = response.Input;
+                        okPressed = true;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    error = true;
+
+                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage, ex));
+                }
+                finally
+                {
+                    dialogCloseEvent.Set();
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            userText = error ? null : inputText;
+
+            return error || okPressed;
+        }
+
+        public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
+        {
+            device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
+            _parent.ViewModel.AppHost?.Stop();
+        }
+
+        public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool showDetails = false;
+
+            Dispatcher.UIThread.InvokeAsync(async () =>
+            {
+                try
+                {
+                    ErrorAppletWindow msgDialog = new(_parent, buttons, message)
+                    {
+                        Title = title,
+                        WindowStartupLocation = WindowStartupLocation.CenterScreen,
+                        Width = 400,
+                    };
+
+                    object response = await msgDialog.Run();
+
+                    if (response != null && buttons != null && buttons.Length > 1 && (int)response != buttons.Length - 1)
+                    {
+                        showDetails = true;
+                    }
+
+                    dialogCloseEvent.Set();
+
+                    msgDialog.Close();
+                }
+                catch (Exception ex)
+                {
+                    dialogCloseEvent.Set();
+
+                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogErrorAppletErrorExceptionMessage, ex));
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            return showDetails;
+        }
+
+        public IDynamicTextInputHandler CreateDynamicTextInputHandler()
+        {
+            return new AvaloniaDynamicTextInputHandler(_parent);
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
deleted file mode 100644
index e1193910..00000000
--- a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Threading;
-using FluentAvalonia.UI.Controls;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Controls;
-using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Windows;
-using Ryujinx.HLE;
-using Ryujinx.HLE.HOS.Applets;
-using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
-using Ryujinx.HLE.Ui;
-using System;
-using System.Threading;
-
-namespace Ryujinx.Ava.UI.Applet
-{
-    internal class AvaHostUiHandler : IHostUiHandler
-    {
-        private readonly MainWindow _parent;
-
-        public IHostUiTheme HostUiTheme { get; }
-
-        public AvaHostUiHandler(MainWindow parent)
-        {
-            _parent = parent;
-
-            HostUiTheme = new AvaloniaHostUiTheme(parent);
-        }
-
-        public bool DisplayMessageDialog(ControllerAppletUiArgs args)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool okPressed = false;
-
-            Dispatcher.UIThread.InvokeAsync(async () =>
-            {
-                var response = await ControllerAppletDialog.ShowControllerAppletDialog(_parent, args);
-                if (response == UserResult.Ok)
-                {
-                    okPressed = true;
-                }
-
-                dialogCloseEvent.Set();
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            return okPressed;
-        }
-
-        public bool DisplayMessageDialog(string title, string message)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool okPressed = false;
-
-            Dispatcher.UIThread.InvokeAsync(async () =>
-            {
-                try
-                {
-                    ManualResetEvent deferEvent = new(false);
-
-                    bool opened = false;
-
-                    UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
-                       title,
-                       message,
-                       "",
-                       LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
-                       "",
-                       LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
-                       (int)Symbol.Important,
-                       deferEvent,
-                       async window =>
-                       {
-                           if (opened)
-                           {
-                               return;
-                           }
-
-                           opened = true;
-
-                           _parent.SettingsWindow = new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
-
-                           await _parent.SettingsWindow.ShowDialog(window);
-
-                           _parent.SettingsWindow = null;
-
-                           opened = false;
-                       });
-
-                    if (response == UserResult.Ok)
-                    {
-                        okPressed = true;
-                    }
-
-                    dialogCloseEvent.Set();
-                }
-                catch (Exception ex)
-                {
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageDialogErrorExceptionMessage, ex));
-
-                    dialogCloseEvent.Set();
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            return okPressed;
-        }
-
-        public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool okPressed = false;
-            bool error = false;
-            string inputText = args.InitialText ?? "";
-
-            Dispatcher.UIThread.InvokeAsync(async () =>
-            {
-                try
-                {
-                    var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
-
-                    if (response.Result == UserResult.Ok)
-                    {
-                        inputText = response.Input;
-                        okPressed = true;
-                    }
-                }
-                catch (Exception ex)
-                {
-                    error = true;
-
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage, ex));
-                }
-                finally
-                {
-                    dialogCloseEvent.Set();
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            userText = error ? null : inputText;
-
-            return error || okPressed;
-        }
-
-        public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
-        {
-            device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
-            _parent.ViewModel.AppHost?.Stop();
-        }
-
-        public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool showDetails = false;
-
-            Dispatcher.UIThread.InvokeAsync(async () =>
-            {
-                try
-                {
-                    ErrorAppletWindow msgDialog = new(_parent, buttons, message)
-                    {
-                        Title = title,
-                        WindowStartupLocation = WindowStartupLocation.CenterScreen,
-                        Width = 400,
-                    };
-
-                    object response = await msgDialog.Run();
-
-                    if (response != null && buttons != null && buttons.Length > 1 && (int)response != buttons.Length - 1)
-                    {
-                        showDetails = true;
-                    }
-
-                    dialogCloseEvent.Set();
-
-                    msgDialog.Close();
-                }
-                catch (Exception ex)
-                {
-                    dialogCloseEvent.Set();
-
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogErrorAppletErrorExceptionMessage, ex));
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            return showDetails;
-        }
-
-        public IDynamicTextInputHandler CreateDynamicTextInputHandler()
-        {
-            return new AvaloniaDynamicTextInputHandler(_parent);
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
index 2411659f..531d0061 100644
--- a/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
+++ b/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
@@ -5,7 +5,7 @@ using Avalonia.Threading;
 using Ryujinx.Ava.Input;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Windows;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using System;
 using System.Threading;
 using HidKey = Ryujinx.Common.Configuration.Hid.Key;
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUITheme.cs b/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUITheme.cs
new file mode 100644
index 00000000..016fb484
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUITheme.cs
@@ -0,0 +1,41 @@
+using Avalonia.Media;
+using Ryujinx.Ava.UI.Windows;
+using Ryujinx.HLE.UI;
+using System;
+
+namespace Ryujinx.Ava.UI.Applet
+{
+    class AvaloniaHostUITheme : IHostUITheme
+    {
+        public AvaloniaHostUITheme(MainWindow parent)
+        {
+            FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) ? "Segoe UI Variable" : parent.FontFamily.Name;
+            DefaultBackgroundColor = BrushToThemeColor(parent.Background);
+            DefaultForegroundColor = BrushToThemeColor(parent.Foreground);
+            DefaultBorderColor = BrushToThemeColor(parent.BorderBrush);
+            SelectionBackgroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionBrush);
+            SelectionForegroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionForegroundBrush);
+        }
+
+        public string FontFamily { get; }
+
+        public ThemeColor DefaultBackgroundColor { get; }
+        public ThemeColor DefaultForegroundColor { get; }
+        public ThemeColor DefaultBorderColor { get; }
+        public ThemeColor SelectionBackgroundColor { get; }
+        public ThemeColor SelectionForegroundColor { get; }
+
+        private static ThemeColor BrushToThemeColor(IBrush brush)
+        {
+            if (brush is SolidColorBrush solidColor)
+            {
+                return new ThemeColor((float)solidColor.Color.A / 255,
+                    (float)solidColor.Color.R / 255,
+                    (float)solidColor.Color.G / 255,
+                    (float)solidColor.Color.B / 255);
+            }
+
+            return new ThemeColor();
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs b/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
deleted file mode 100644
index 4ee177d7..00000000
--- a/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Avalonia.Media;
-using Ryujinx.Ava.UI.Windows;
-using Ryujinx.HLE.Ui;
-using System;
-
-namespace Ryujinx.Ava.UI.Applet
-{
-    class AvaloniaHostUiTheme : IHostUiTheme
-    {
-        public AvaloniaHostUiTheme(MainWindow parent)
-        {
-            FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) ? "Segoe UI Variable" : parent.FontFamily.Name;
-            DefaultBackgroundColor = BrushToThemeColor(parent.Background);
-            DefaultForegroundColor = BrushToThemeColor(parent.Foreground);
-            DefaultBorderColor = BrushToThemeColor(parent.BorderBrush);
-            SelectionBackgroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionBrush);
-            SelectionForegroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionForegroundBrush);
-        }
-
-        public string FontFamily { get; }
-
-        public ThemeColor DefaultBackgroundColor { get; }
-        public ThemeColor DefaultForegroundColor { get; }
-        public ThemeColor DefaultBorderColor { get; }
-        public ThemeColor SelectionBackgroundColor { get; }
-        public ThemeColor SelectionForegroundColor { get; }
-
-        private static ThemeColor BrushToThemeColor(IBrush brush)
-        {
-            if (brush is SolidColorBrush solidColor)
-            {
-                return new ThemeColor((float)solidColor.Color.A / 255,
-                    (float)solidColor.Color.R / 255,
-                    (float)solidColor.Color.G / 255,
-                    (float)solidColor.Color.B / 255);
-            }
-
-            return new ThemeColor();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs b/src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs
index f7d751a6..279af07c 100644
--- a/src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.Ava.UI.Applet
 
         private readonly MainWindow _mainWindow;
 
-        public ControllerAppletDialog(MainWindow mainWindow, ControllerAppletUiArgs args)
+        public ControllerAppletDialog(MainWindow mainWindow, ControllerAppletUIArgs args)
         {
             if (args.PlayerCountMin == args.PlayerCountMax)
             {
@@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Applet
             InitializeComponent();
         }
 
-        public static async Task<UserResult> ShowControllerAppletDialog(MainWindow window, ControllerAppletUiArgs args)
+        public static async Task<UserResult> ShowControllerAppletDialog(MainWindow window, ControllerAppletUIArgs args)
         {
             ContentDialog contentDialog = new();
             UserResult result = UserResult.Cancel;
diff --git a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml
index 6186b7d9..51f37051 100644
--- a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml
+++ b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml
@@ -34,7 +34,7 @@
             Height="80"
             MinWidth="50"
             Margin="5,10,20,10"
-            Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
+            Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
         <TextBlock
             Grid.Row="1"
             Grid.Column="1"
diff --git a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml
index 7e083606..b1c84734 100644
--- a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml
+++ b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml
@@ -31,7 +31,7 @@
             MinWidth="50"
             Margin="5,10,20,10"
             VerticalAlignment="Center"
-            Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
+            Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
         <TextBlock
             Grid.Row="1"
             Grid.Column="1"
diff --git a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs
index 5a4cd855..af3837e4 100644
--- a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs
@@ -54,7 +54,7 @@ namespace Ryujinx.Ava.UI.Controls
         public string MainText { get; set; } = "";
         public string SecondaryText { get; set; } = "";
 
-        public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUiArgs args)
+        public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUIArgs args)
         {
             ContentDialog contentDialog = new();
 
diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
index 01d97709..1fb9d3b3 100644
--- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
@@ -11,8 +11,8 @@ using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common.Configuration;
 using Ryujinx.HLE.HOS;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs
index 821d6fd9..ee15bc8d 100644
--- a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs
@@ -3,7 +3,7 @@ using Avalonia.Input;
 using Avalonia.Interactivity;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 
 namespace Ryujinx.Ava.UI.Controls
diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs
index dd60503a..8681158f 100644
--- a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs
@@ -3,7 +3,7 @@ using Avalonia.Input;
 using Avalonia.Interactivity;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 
 namespace Ryujinx.Ava.UI.Controls
diff --git a/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml b/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml
index c5041230..09fa0404 100644
--- a/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml
+++ b/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml
@@ -26,7 +26,7 @@
             Height="70"
             MinWidth="50"
             Margin="5,10,20,10"
-            Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
+            Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
         <StackPanel
             Grid.Row="1"
             Grid.Column="1"
@@ -39,4 +39,4 @@
                 VerticalAlignment="Center" />
         </StackPanel>
     </Grid>
-</Window>
\ No newline at end of file
+</Window>
diff --git a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs b/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
index cd63a99b..bc5622b5 100644
--- a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
@@ -1,5 +1,5 @@
 using Avalonia.Interactivity;
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 
 namespace Ryujinx.Ava.UI.Helpers
 {
diff --git a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
index b9d919f9..15b7ddd1 100644
--- a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
@@ -383,7 +383,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 {
                     result = ContentDialogResult.None;
 
-                    Logger.Warning?.Print(LogClass.Ui, "Content dialog overlay failed to populate. Default value has been returned.");
+                    Logger.Warning?.Print(LogClass.UI, "Content dialog overlay failed to populate. Default value has been returned.");
                 }
 
                 return result;
diff --git a/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs b/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs
index b61a924f..26fe36c4 100644
--- a/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs
@@ -1,7 +1,7 @@
 using Avalonia.Data.Converters;
 using Avalonia.Markup.Xaml;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Globalization;
 
diff --git a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
index 0b178988..fc714541 100644
--- a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
@@ -39,12 +39,12 @@ namespace Ryujinx.Ava.UI.Helpers
 
         public void Log(AvaLogLevel level, string area, object source, string messageTemplate)
         {
-            GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, null));
+            GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, null));
         }
 
         public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues)
         {
-            GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, propertyValues));
+            GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, propertyValues));
         }
 
         private static string Format(AvaLogLevel level, string area, string template, object source, object[] v)
diff --git a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs b/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
index fc82bd6b..9a44b862 100644
--- a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
@@ -1,6 +1,6 @@
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Helper;
 using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Helpers
diff --git a/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs b/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs
index 8340d39d..224f78f4 100644
--- a/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs
+++ b/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs
@@ -1,4 +1,4 @@
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 using System.Collections.Generic;
 
diff --git a/src/Ryujinx.Ava/UI/Models/Generic/TimePlayedSortComparer.cs b/src/Ryujinx.Ava/UI/Models/Generic/TimePlayedSortComparer.cs
index d53ff566..f0fb035d 100644
--- a/src/Ryujinx.Ava/UI/Models/Generic/TimePlayedSortComparer.cs
+++ b/src/Ryujinx.Ava/UI/Models/Generic/TimePlayedSortComparer.cs
@@ -1,4 +1,4 @@
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 using System.Collections.Generic;
 
diff --git a/src/Ryujinx.Ava/UI/Models/SaveModel.cs b/src/Ryujinx.Ava/UI/Models/SaveModel.cs
index 7b476932..d6dea2f6 100644
--- a/src/Ryujinx.Ava/UI/Models/SaveModel.cs
+++ b/src/Ryujinx.Ava/UI/Models/SaveModel.cs
@@ -3,8 +3,8 @@ using LibHac.Ncm;
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common.Helper;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
index fa55c8d3..3bf19b43 100644
--- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
+++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
@@ -3,8 +3,8 @@ using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Platform;
 using Ryujinx.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using SPB.Graphics;
 using SPB.Platform;
 using SPB.Platform.GLX;
diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs
index 769a1c91..3842301d 100644
--- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs
+++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs
@@ -3,7 +3,7 @@ using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.OpenGL;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using SPB.Graphics;
 using SPB.Graphics.Exceptions;
 using SPB.Graphics.OpenGL;
@@ -75,7 +75,7 @@ namespace Ryujinx.Ava.UI.Renderer
                     throw;
                 }
 
-                Logger.Warning?.Print(LogClass.Ui, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
+                Logger.Warning?.Print(LogClass.UI, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
             }
         }
 
diff --git a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs
index 12c18e4a..d055d9ea 100644
--- a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs
@@ -1,7 +1,7 @@
 using Avalonia;
 using Avalonia.Controls;
 using Ryujinx.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System;
 
 namespace Ryujinx.Ava.UI.Renderer
diff --git a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs
index 70ede4c1..6020f40e 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs
@@ -3,7 +3,7 @@ using Avalonia.Platform;
 using Avalonia.Threading;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System;
 using System.Net.Http;
 using System.Net.NetworkInformation;
@@ -87,19 +87,19 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             Version = Program.Version;
 
-            if (ConfigurationState.Instance.Ui.BaseStyle.Value == "Light")
+            if (ConfigurationState.Instance.UI.BaseStyle.Value == "Light")
             {
-                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.Ui.Common")));
-                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.Ui.Common")));
-                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.Ui.Common")));
-                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.Ui.Common")));
+                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.UI.Common")));
+                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.UI.Common")));
+                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.UI.Common")));
+                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.UI.Common")));
             }
             else
             {
-                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.Ui.Common")));
-                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.Ui.Common")));
-                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.Ui.Common")));
-                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.Ui.Common")));
+                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.UI.Common")));
+                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.UI.Common")));
+                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.UI.Common")));
+                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.UI.Common")));
             }
 
             Dispatcher.UIThread.InvokeAsync(DownloadPatronsJson);
diff --git a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs
index 0e0d858a..8f09568a 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs
@@ -9,7 +9,7 @@ using Ryujinx.Common;
 using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Models.Amiibo;
+using Ryujinx.UI.Common.Models.Amiibo;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -65,7 +65,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             _amiiboSeries = new ObservableCollection<string>();
             _amiibos = new AvaloniaList<AmiiboApi>();
 
-            _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.Ui.Common/Resources/Logo_Amiibo.png");
+            _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png");
 
             _ = LoadContentAsync();
         }
diff --git a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
index 042803f3..71ad2c12 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
@@ -19,7 +19,7 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
 using Ryujinx.Input;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -35,10 +35,10 @@ namespace Ryujinx.Ava.UI.ViewModels
     public class ControllerInputViewModel : BaseModel, IDisposable
     {
         private const string Disabled = "disabled";
-        private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
-        private const string JoyConPairResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg";
-        private const string JoyConLeftResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg";
-        private const string JoyConRightResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg";
+        private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg";
+        private const string JoyConPairResource = "Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg";
+        private const string JoyConLeftResource = "Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg";
+        private const string JoyConRightResource = "Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg";
         private const string KeyboardString = "keyboard";
         private const string ControllerString = "controller";
         private readonly MainWindow _mainWindow;
diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
index 243d870a..17bd69b1 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
@@ -25,13 +25,13 @@ using Ryujinx.HLE;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Input.HLE;
 using Ryujinx.Modules;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using SixLabors.ImageSharp.PixelFormats;
 using System;
 using System.Collections.Generic;
@@ -138,7 +138,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             InputManager inputManager,
             UserChannelPersistence userChannelPersistence,
             LibHacHorizonManager libHacHorizonManager,
-            IHostUiHandler uiHandler,
+            IHostUIHandler uiHandler,
             Action<bool> showLoading,
             Action<bool> switchToGameControl,
             Action<Control> setMainContent,
@@ -685,10 +685,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool StartGamesInFullscreen
         {
-            get => ConfigurationState.Instance.Ui.StartFullscreen;
+            get => ConfigurationState.Instance.UI.StartFullscreen;
             set
             {
-                ConfigurationState.Instance.Ui.StartFullscreen.Value = value;
+                ConfigurationState.Instance.UI.StartFullscreen.Value = value;
 
                 ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
 
@@ -698,10 +698,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool ShowConsole
         {
-            get => ConfigurationState.Instance.Ui.ShowConsole;
+            get => ConfigurationState.Instance.UI.ShowConsole;
             set
             {
-                ConfigurationState.Instance.Ui.ShowConsole.Value = value;
+                ConfigurationState.Instance.UI.ShowConsole.Value = value;
 
                 ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
 
@@ -743,10 +743,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public Glyph Glyph
         {
-            get => (Glyph)ConfigurationState.Instance.Ui.GameListViewMode.Value;
+            get => (Glyph)ConfigurationState.Instance.UI.GameListViewMode.Value;
             set
             {
-                ConfigurationState.Instance.Ui.GameListViewMode.Value = (int)value;
+                ConfigurationState.Instance.UI.GameListViewMode.Value = (int)value;
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(IsGrid));
@@ -758,9 +758,9 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool ShowNames
         {
-            get => ConfigurationState.Instance.Ui.ShowNames && ConfigurationState.Instance.Ui.GridSize > 1; set
+            get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1; set
             {
-                ConfigurationState.Instance.Ui.ShowNames.Value = value;
+                ConfigurationState.Instance.UI.ShowNames.Value = value;
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(GridSizeScale));
@@ -772,10 +772,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         internal ApplicationSort SortMode
         {
-            get => (ApplicationSort)ConfigurationState.Instance.Ui.ApplicationSort.Value;
+            get => (ApplicationSort)ConfigurationState.Instance.UI.ApplicationSort.Value;
             private set
             {
-                ConfigurationState.Instance.Ui.ApplicationSort.Value = (int)value;
+                ConfigurationState.Instance.UI.ApplicationSort.Value = (int)value;
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(SortName));
@@ -788,7 +788,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             get
             {
-                return ConfigurationState.Instance.Ui.GridSize.Value switch
+                return ConfigurationState.Instance.UI.GridSize.Value switch
                 {
                     1 => 78,
                     2 => 100,
@@ -803,7 +803,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             get
             {
-                return ConfigurationState.Instance.Ui.GridSize.Value switch
+                return ConfigurationState.Instance.UI.GridSize.Value switch
                 {
                     1 => 120,
                     2 => ShowNames ? 210 : 150,
@@ -816,10 +816,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public int GridSizeScale
         {
-            get => ConfigurationState.Instance.Ui.GridSize;
+            get => ConfigurationState.Instance.UI.GridSize;
             set
             {
-                ConfigurationState.Instance.Ui.GridSize.Value = value;
+                ConfigurationState.Instance.UI.GridSize.Value = value;
 
                 if (value < 2)
                 {
@@ -860,10 +860,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool IsAscending
         {
-            get => ConfigurationState.Instance.Ui.IsAscendingOrder;
+            get => ConfigurationState.Instance.UI.IsAscendingOrder;
             private set
             {
-                ConfigurationState.Instance.Ui.IsAscendingOrder.Value = value;
+                ConfigurationState.Instance.UI.IsAscendingOrder.Value = value;
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(SortMode));
@@ -919,7 +919,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         public RendererHost RendererHostControl { get; private set; }
         public bool IsClosing { get; set; }
         public LibHacHorizonManager LibHacHorizonManager { get; internal set; }
-        public IHostUiHandler UiHandler { get; internal set; }
+        public IHostUIHandler UiHandler { get; internal set; }
         public bool IsSortedByFavorite => SortMode == ApplicationSort.Favorite;
         public bool IsSortedByTitle => SortMode == ApplicationSort.Title;
         public bool IsSortedByDeveloper => SortMode == ApplicationSort.Developer;
@@ -928,10 +928,10 @@ namespace Ryujinx.Ava.UI.ViewModels
         public bool IsSortedByType => SortMode == ApplicationSort.FileType;
         public bool IsSortedBySize => SortMode == ApplicationSort.FileSize;
         public bool IsSortedByPath => SortMode == ApplicationSort.Path;
-        public bool IsGridSmall => ConfigurationState.Instance.Ui.GridSize == 1;
-        public bool IsGridMedium => ConfigurationState.Instance.Ui.GridSize == 2;
-        public bool IsGridLarge => ConfigurationState.Instance.Ui.GridSize == 3;
-        public bool IsGridHuge => ConfigurationState.Instance.Ui.GridSize == 4;
+        public bool IsGridSmall => ConfigurationState.Instance.UI.GridSize == 1;
+        public bool IsGridMedium => ConfigurationState.Instance.UI.GridSize == 2;
+        public bool IsGridLarge => ConfigurationState.Instance.UI.GridSize == 3;
+        public bool IsGridHuge => ConfigurationState.Instance.UI.GridSize == 4;
 
         #endregion
 
@@ -1245,7 +1245,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void LoadConfigurableHotKeys()
         {
-            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
+            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI, out var showUiKey))
             {
                 ShowUiKey = new KeyGesture(showUiKey);
             }
@@ -1385,7 +1385,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             if (Program.PreviewerDetached)
             {
-                ConfigurationState.Instance.Ui.LanguageCode.Value = (string)languageCode;
+                ConfigurationState.Instance.UI.LanguageCode.Value = (string)languageCode;
                 ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
             }
         }
diff --git a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
index 9e462a90..bcaa0860 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
@@ -16,8 +16,8 @@ using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.Vulkan;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS.Services.Time.TimeZone;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration.System;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Configuration.System;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -408,9 +408,9 @@ namespace Ryujinx.Ava.UI.ViewModels
             HideCursor = (int)config.HideCursor.Value;
 
             GameDirectories.Clear();
-            GameDirectories.AddRange(config.Ui.GameDirs.Value);
+            GameDirectories.AddRange(config.UI.GameDirs.Value);
 
-            BaseStyleIndex = config.Ui.BaseStyle == "Light" ? 0 : 1;
+            BaseStyleIndex = config.UI.BaseStyle == "Light" ? 0 : 1;
 
             // Input
             EnableDockedMode = config.System.EnableDockedMode;
@@ -494,10 +494,10 @@ namespace Ryujinx.Ava.UI.ViewModels
             if (_directoryChanged)
             {
                 List<string> gameDirs = new(GameDirectories);
-                config.Ui.GameDirs.Value = gameDirs;
+                config.UI.GameDirs.Value = gameDirs;
             }
 
-            config.Ui.BaseStyle.Value = BaseStyleIndex == 0 ? "Light" : "Dark";
+            config.UI.BaseStyle.Value = BaseStyleIndex == 0 ? "Light" : "Dark";
 
             // Input
             config.System.EnableDockedMode.Value = EnableDockedMode;
diff --git a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
index 8a287eca..5989ce09 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
@@ -17,7 +17,7 @@ using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 using System.Collections.Generic;
 using System.IO;
diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
index 9c0e683a..8dff5086 100644
--- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
@@ -10,9 +10,9 @@ using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
 using Ryujinx.Common.Utilities;
 using Ryujinx.Modules;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Main
                 checkBoxes.Add(new CheckBox
                 {
                     Content = $".{fileName}",
-                    IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.Ui.ShownFileTypes),
+                    IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.UI.ShownFileTypes),
                     Command = MiniCommand.Create(() => Window.ToggleFileType(fileName)),
                 });
             }
diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
index 822045d4..239a7cbf 100644
--- a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
@@ -5,7 +5,7 @@ using Avalonia.Interactivity;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System;
 
 namespace Ryujinx.Ava.UI.Views.Main
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml
index a53c1dfe..b4eae01e 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml
@@ -45,7 +45,7 @@
                     <TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysShowUiHotkey}" Width="230" />
                     <ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
                         <TextBlock
-                            Text="{Binding KeyboardHotkeys.ShowUi, Mode=TwoWay, Converter={StaticResource Key}}"
+                            Text="{Binding KeyboardHotkeys.ShowUI, Mode=TwoWay, Converter={StaticResource Key}}"
                             TextAlignment="Center" />
                     </ToggleButton>
                 </StackPanel>
diff --git a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
index a0657140..69fa8251 100644
--- a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
+++ b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml
@@ -51,7 +51,7 @@
                         Spacing="10">
                         <Image
                             Height="80"
-                            Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common"
+                            Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common"
                             HorizontalAlignment="Center"
                             IsHitTestVisible="True" />
                         <WrapPanel
diff --git a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs
index 7f28ad35..c32661b0 100644
--- a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs
@@ -7,7 +7,7 @@ using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Helper;
 using System.Threading.Tasks;
 using Button = Avalonia.Controls.Button;
 
diff --git a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs
index 57106638..8829cb10 100644
--- a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs
@@ -1,7 +1,7 @@
 using Avalonia.Interactivity;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Ui.Common.Models.Amiibo;
+using Ryujinx.UI.Common.Models.Amiibo;
 
 namespace Ryujinx.Ava.UI.Windows
 {
diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
index 46441faa..d78e48a4 100644
--- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
@@ -3,7 +3,7 @@ using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Models;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
-using Ryujinx.Ui.App.Common;
+using Ryujinx.UI.App.Common;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
diff --git a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs
index dfe8807b..0c02fa0f 100644
--- a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs
@@ -7,7 +7,7 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Helper;
 using System.Threading.Tasks;
 using Button = Avalonia.Controls.Button;
 
diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
index ae26b651..33a9af5b 100644
--- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
@@ -18,10 +18,10 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.Input.HLE;
 using Ryujinx.Input.SDL2;
 using Ryujinx.Modules;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.IO;
 using System.Runtime.Versioning;
@@ -40,7 +40,7 @@ namespace Ryujinx.Ava.UI.Windows
         private static bool _deferLoad;
         private static string _launchPath;
         private static bool _startFullscreen;
-        internal readonly AvaHostUiHandler UiHandler;
+        internal readonly AvaHostUIHandler UiHandler;
 
         public VirtualFileSystem VirtualFileSystem { get; private set; }
         public ContentManager ContentManager { get; private set; }
@@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Windows
             InitializeComponent();
             Load();
 
-            UiHandler = new AvaHostUiHandler(this);
+            UiHandler = new AvaHostUIHandler(this);
 
             ViewModel.Title = $"Ryujinx {Program.Version}";
 
@@ -319,13 +319,13 @@ namespace Ryujinx.Ava.UI.Windows
 
         private void SetWindowSizePosition()
         {
-            PixelPoint savedPoint = new(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX,
-                                        ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY);
+            PixelPoint savedPoint = new(ConfigurationState.Instance.UI.WindowStartup.WindowPositionX,
+                                        ConfigurationState.Instance.UI.WindowStartup.WindowPositionY);
 
-            ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor;
-            ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor;
+            ViewModel.WindowHeight = ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor;
+            ViewModel.WindowWidth = ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor;
 
-            ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value ? WindowState.Maximized : WindowState.Normal;
+            ViewModel.WindowState = ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value ? WindowState.Maximized : WindowState.Normal;
 
             if (CheckScreenBounds(savedPoint))
             {
@@ -353,13 +353,13 @@ namespace Ryujinx.Ava.UI.Windows
 
         private void SaveWindowSizePosition()
         {
-            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight.Value = (int)Height;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth.Value = (int)Width;
+            ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight.Value = (int)Height;
+            ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth.Value = (int)Width;
 
-            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX.Value = Position.X;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY.Value = Position.Y;
+            ConfigurationState.Instance.UI.WindowStartup.WindowPositionX.Value = Position.X;
+            ConfigurationState.Instance.UI.WindowStartup.WindowPositionY.Value = Position.Y;
 
-            ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
+            ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
 
             MainWindowViewModel.SaveConfig();
         }
@@ -512,12 +512,12 @@ namespace Ryujinx.Ava.UI.Windows
             _ = fileType switch
             {
 #pragma warning disable IDE0055 // Disable formatting
-                "NSP"  => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP,
-                "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0,
-                "XCI"  => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI,
-                "NCA"  => ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NCA,
-                "NRO"  => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO,
-                "NSO"  => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO,
+                "NSP"  => ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value  = !ConfigurationState.Instance.UI.ShownFileTypes.NSP,
+                "PFS0" => ConfigurationState.Instance.UI.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.UI.ShownFileTypes.PFS0,
+                "XCI"  => ConfigurationState.Instance.UI.ShownFileTypes.XCI.Value  = !ConfigurationState.Instance.UI.ShownFileTypes.XCI,
+                "NCA"  => ConfigurationState.Instance.UI.ShownFileTypes.NCA.Value  = !ConfigurationState.Instance.UI.ShownFileTypes.NCA,
+                "NRO"  => ConfigurationState.Instance.UI.ShownFileTypes.NRO.Value  = !ConfigurationState.Instance.UI.ShownFileTypes.NRO,
+                "NSO"  => ConfigurationState.Instance.UI.ShownFileTypes.NSO.Value  = !ConfigurationState.Instance.UI.ShownFileTypes.NSO,
                 _  => throw new ArgumentOutOfRangeException(fileType),
 #pragma warning restore IDE0055
             };
@@ -537,7 +537,7 @@ namespace Ryujinx.Ava.UI.Windows
 
             Thread applicationLibraryThread = new(() =>
             {
-                ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs, ConfigurationState.Instance.System.Language);
+                ApplicationLibrary.LoadApplications(ConfigurationState.Instance.UI.GameDirs, ConfigurationState.Instance.System.Language);
 
                 _isLoading = false;
             })
diff --git a/src/Ryujinx.Ava/UI/Windows/ModManagerWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/ModManagerWindow.axaml.cs
index 5de09ba0..d9ae0d4f 100644
--- a/src/Ryujinx.Ava/UI/Windows/ModManagerWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/ModManagerWindow.axaml.cs
@@ -6,7 +6,7 @@ using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Helper;
 using System.Threading.Tasks;
 using Button = Avalonia.Controls.Button;
 
diff --git a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
index 3cd12bc8..a12d2b3e 100644
--- a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
+++ b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
@@ -4,7 +4,7 @@ using Avalonia.Media;
 using Avalonia.Media.Imaging;
 using Avalonia.Platform;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.UI.Common.Configuration;
 using System.IO;
 using System.Reflection;
 
@@ -19,7 +19,7 @@ namespace Ryujinx.Ava.UI.Windows
             WindowStartupLocation = WindowStartupLocation.CenterOwner;
             TransparencyLevelHint = new[] { WindowTransparencyLevel.None };
 
-            using Stream stream = Assembly.GetAssembly(typeof(ConfigurationState)).GetManifestResourceStream("Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
+            using Stream stream = Assembly.GetAssembly(typeof(ConfigurationState)).GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
 
             Icon = new WindowIcon(stream);
             stream.Position = 0;
diff --git a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs
index 7ece6335..f3ac6960 100644
--- a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs
@@ -7,7 +7,7 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI.Common.Helper;
 using System.Threading.Tasks;
 using Button = Avalonia.Controls.Button;
 
diff --git a/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs b/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
index b4f2f946..e9c163cf 100644
--- a/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
+++ b/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
@@ -6,7 +6,7 @@ namespace Ryujinx.Common.Configuration.Hid
     {
         public Key ToggleVsync { get; set; }
         public Key Screenshot { get; set; }
-        public Key ShowUi { get; set; }
+        public Key ShowUI { get; set; }
         public Key Pause { get; set; }
         public Key ToggleMute { get; set; }
         public Key ResScaleUp { get; set; }
diff --git a/src/Ryujinx.Common/Logging/LogClass.cs b/src/Ryujinx.Common/Logging/LogClass.cs
index f277dd06..1b404a06 100644
--- a/src/Ryujinx.Common/Logging/LogClass.cs
+++ b/src/Ryujinx.Common/Logging/LogClass.cs
@@ -70,7 +70,7 @@ namespace Ryujinx.Common.Logging
         ServiceVi,
         SurfaceFlinger,
         TamperMachine,
-        Ui,
+        UI,
         Vic,
     }
 }
diff --git a/src/Ryujinx.HLE/HLEConfiguration.cs b/src/Ryujinx.HLE/HLEConfiguration.cs
index f589bfdd..955fee4b 100644
--- a/src/Ryujinx.HLE/HLEConfiguration.cs
+++ b/src/Ryujinx.HLE/HLEConfiguration.cs
@@ -7,7 +7,7 @@ using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.HLE.HOS.SystemState;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using System;
 
 namespace Ryujinx.HLE
@@ -63,7 +63,7 @@ namespace Ryujinx.HLE
         /// The handler for various UI related operations needed outside of HLE.
         /// </summary>
         /// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
-        internal readonly IHostUiHandler HostUiHandler;
+        internal readonly IHostUIHandler HostUIHandler;
 
         /// <summary>
         /// Control the memory configuration used by the emulation context.
@@ -177,7 +177,7 @@ namespace Ryujinx.HLE
                                 IRenderer gpuRenderer,
                                 IHardwareDeviceDriver audioDeviceDriver,
                                 MemoryConfiguration memoryConfiguration,
-                                IHostUiHandler hostUiHandler,
+                                IHostUIHandler hostUIHandler,
                                 SystemLanguage systemLanguage,
                                 RegionCode region,
                                 bool enableVsync,
@@ -204,7 +204,7 @@ namespace Ryujinx.HLE
             GpuRenderer = gpuRenderer;
             AudioDeviceDriver = audioDeviceDriver;
             MemoryConfiguration = memoryConfiguration;
-            HostUiHandler = hostUiHandler;
+            HostUIHandler = hostUIHandler;
             SystemLanguage = systemLanguage;
             Region = region;
             EnableVsync = enableVsync;
diff --git a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
index 86720217..5ec9d4b0 100644
--- a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
@@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Applets
             PlayerIndex primaryIndex;
             while (!_system.Device.Hid.Npads.Validate(playerMin, playerMax, (ControllerType)privateArg.NpadStyleSet, out configuredCount, out primaryIndex))
             {
-                ControllerAppletUiArgs uiArgs = new()
+                ControllerAppletUIArgs uiArgs = new()
                 {
                     PlayerCountMin = playerMin,
                     PlayerCountMax = playerMax,
@@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Applets
                     IsDocked = _system.State.DockedMode,
                 };
 
-                if (!_system.Device.UiHandler.DisplayMessageDialog(uiArgs))
+                if (!_system.Device.UIHandler.DisplayMessageDialog(uiArgs))
                 {
                     break;
                 }
diff --git a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUIArgs.cs b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUIArgs.cs
new file mode 100644
index 00000000..10cba58b
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUIArgs.cs
@@ -0,0 +1,14 @@
+using Ryujinx.HLE.HOS.Services.Hid;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Applets
+{
+    public struct ControllerAppletUIArgs
+    {
+        public int PlayerCountMin;
+        public int PlayerCountMax;
+        public ControllerType SupportedStyles;
+        public IEnumerable<PlayerIndex> SupportedPlayers;
+        public bool IsDocked;
+    }
+}
diff --git a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUiArgs.cs b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUiArgs.cs
deleted file mode 100644
index bf440515..00000000
--- a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerAppletUiArgs.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Ryujinx.HLE.HOS.Services.Hid;
-using System.Collections.Generic;
-
-namespace Ryujinx.HLE.HOS.Applets
-{
-    public struct ControllerAppletUiArgs
-    {
-        public int PlayerCountMin;
-        public int PlayerCountMax;
-        public ControllerType SupportedStyles;
-        public IEnumerable<PlayerIndex> SupportedPlayers;
-        public bool IsDocked;
-    }
-}
diff --git a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs
index 5c474f22..7ee9b9e9 100644
--- a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs
@@ -166,13 +166,13 @@ namespace Ryujinx.HLE.HOS.Applets.Error
 
             string[] buttons = GetButtonsText(module, description, "DlgBtn");
 
-            bool showDetails = _horizon.Device.UiHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons);
+            bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons);
             if (showDetails)
             {
                 message = GetMessageText(module, description, "FlvMsg");
                 buttons = GetButtonsText(module, description, "FlvBtn");
 
-                _horizon.Device.UiHandler.DisplayErrorAppletDialog($"Details: {module}-{description:0000}", "\n" + message, buttons);
+                _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Details: {module}-{description:0000}", "\n" + message, buttons);
             }
         }
 
@@ -200,12 +200,12 @@ namespace Ryujinx.HLE.HOS.Applets.Error
 
             buttons.Add("OK");
 
-            bool showDetails = _horizon.Device.UiHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber}", "\n" + messageText, buttons.ToArray());
+            bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber}", "\n" + messageText, buttons.ToArray());
             if (showDetails)
             {
                 buttons.RemoveAt(0);
 
-                _horizon.Device.UiHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber} (Details)", "\n" + detailsText, buttons.ToArray());
+                _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber} (Details)", "\n" + detailsText, buttons.ToArray());
             }
         }
 
diff --git a/src/Ryujinx.HLE/HOS/Applets/IApplet.cs b/src/Ryujinx.HLE/HOS/Applets/IApplet.cs
index 5ccf3994..985887c4 100644
--- a/src/Ryujinx.HLE/HOS/Applets/IApplet.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/IApplet.cs
@@ -1,5 +1,5 @@
 using Ryujinx.HLE.HOS.Services.Am.AppletAE;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Memory;
 using System;
 using System.Runtime.InteropServices;
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs
index 432bf6a8..0462a5b0 100644
--- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs
@@ -4,8 +4,8 @@ using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
 using Ryujinx.HLE.HOS.Services.Am.AppletAE;
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
-using Ryujinx.HLE.Ui;
-using Ryujinx.HLE.Ui.Input;
+using Ryujinx.HLE.UI;
+using Ryujinx.HLE.UI.Input;
 using Ryujinx.Memory;
 using System;
 using System.Diagnostics;
@@ -92,14 +92,14 @@ namespace Ryujinx.HLE.HOS.Applets
                     _keyboardBackgroundInitialize = MemoryMarshal.Read<SoftwareKeyboardInitialize>(keyboardConfig);
                     _backgroundState = InlineKeyboardState.Uninitialized;
 
-                    if (_device.UiHandler == null)
+                    if (_device.UIHandler == null)
                     {
                         Logger.Error?.Print(LogClass.ServiceAm, "GUI Handler is not set, software keyboard applet will not work properly");
                     }
                     else
                     {
                         // Create a text handler that converts keyboard strokes to strings.
-                        _dynamicTextInputHandler = _device.UiHandler.CreateDynamicTextInputHandler();
+                        _dynamicTextInputHandler = _device.UIHandler.CreateDynamicTextInputHandler();
                         _dynamicTextInputHandler.TextChangedEvent += HandleTextChangedEvent;
                         _dynamicTextInputHandler.KeyPressedEvent += HandleKeyPressedEvent;
 
@@ -107,7 +107,7 @@ namespace Ryujinx.HLE.HOS.Applets
                         _npads.NpadButtonDownEvent += HandleNpadButtonDownEvent;
                         _npads.NpadButtonUpEvent += HandleNpadButtonUpEvent;
 
-                        _keyboardRenderer = new SoftwareKeyboardRenderer(_device.UiHandler.HostUiTheme);
+                        _keyboardRenderer = new SoftwareKeyboardRenderer(_device.UIHandler.HostUITheme);
                     }
 
                     return ResultCode.Success;
@@ -199,7 +199,7 @@ namespace Ryujinx.HLE.HOS.Applets
                 _keyboardForegroundConfig.StringLengthMax = 100;
             }
 
-            if (_device.UiHandler == null)
+            if (_device.UIHandler == null)
             {
                 Logger.Warning?.Print(LogClass.Application, "GUI Handler is not set. Falling back to default");
 
@@ -209,7 +209,7 @@ namespace Ryujinx.HLE.HOS.Applets
             else
             {
                 // Call the configured GUI handler to get user's input.
-                var args = new SoftwareKeyboardUiArgs
+                var args = new SoftwareKeyboardUIArgs
                 {
                     KeyboardMode = _keyboardForegroundConfig.Mode,
                     HeaderText = StripUnicodeControlCodes(_keyboardForegroundConfig.HeaderText),
@@ -222,7 +222,7 @@ namespace Ryujinx.HLE.HOS.Applets
                     InitialText = initialText,
                 };
 
-                _lastResult = _device.UiHandler.DisplayInputDialog(args, out _textValue) ? KeyboardResult.Accept : KeyboardResult.Cancel;
+                _lastResult = _device.UIHandler.DisplayInputDialog(args, out _textValue) ? KeyboardResult.Accept : KeyboardResult.Cancel;
                 _textValue ??= initialText ?? DefaultInputText;
             }
 
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRenderer.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRenderer.cs
index f76cce29..3f7516e6 100644
--- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRenderer.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRenderer.cs
@@ -1,4 +1,4 @@
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Memory;
 using System;
 using System.Threading;
@@ -15,13 +15,13 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
 
         private readonly object _stateLock = new();
 
-        private readonly SoftwareKeyboardUiState _state = new();
+        private readonly SoftwareKeyboardUIState _state = new();
         private readonly SoftwareKeyboardRendererBase _renderer;
 
         private readonly TimedAction _textBoxBlinkTimedAction = new();
         private readonly TimedAction _renderAction = new();
 
-        public SoftwareKeyboardRenderer(IHostUiTheme uiTheme)
+        public SoftwareKeyboardRenderer(IHostUITheme uiTheme)
         {
             _renderer = new SoftwareKeyboardRendererBase(uiTheme);
 
@@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
             StartRenderer(_renderAction, _renderer, _state, _stateLock);
         }
 
-        private static void StartTextBoxBlinker(TimedAction timedAction, SoftwareKeyboardUiState state, object stateLock)
+        private static void StartTextBoxBlinker(TimedAction timedAction, SoftwareKeyboardUIState state, object stateLock)
         {
             timedAction.Reset(() =>
             {
@@ -45,9 +45,9 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
             }, TextBoxBlinkSleepMilliseconds);
         }
 
-        private static void StartRenderer(TimedAction timedAction, SoftwareKeyboardRendererBase renderer, SoftwareKeyboardUiState state, object stateLock)
+        private static void StartRenderer(TimedAction timedAction, SoftwareKeyboardRendererBase renderer, SoftwareKeyboardUIState state, object stateLock)
         {
-            SoftwareKeyboardUiState internalState = new();
+            SoftwareKeyboardUIState internalState = new();
 
             bool canCreateSurface = false;
             bool needsUpdate = true;
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
index 3971a33b..75c648ff 100644
--- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
@@ -1,4 +1,4 @@
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Memory;
 using SixLabors.Fonts;
 using SixLabors.ImageSharp;
@@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
         private Point _logoPosition;
         private float _messagePositionY;
 
-        public SoftwareKeyboardRendererBase(IHostUiTheme uiTheme)
+        public SoftwareKeyboardRendererBase(IHostUITheme uiTheme)
         {
             int ryujinxLogoSize = 32;
 
@@ -205,7 +205,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
             });
         }
 
-        public void DrawMutableElements(SoftwareKeyboardUiState state)
+        public void DrawMutableElements(SoftwareKeyboardUIState state)
         {
             if (_surface == null)
             {
@@ -322,7 +322,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
             return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
         }
 
-        private void DrawTextBox(IImageProcessingContext context, SoftwareKeyboardUiState state)
+        private void DrawTextBox(IImageProcessingContext context, SoftwareKeyboardUIState state)
         {
             var inputTextRectangle = MeasureString(state.InputText, _inputTextFont);
 
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIArgs.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIArgs.cs
new file mode 100644
index 00000000..854f04a3
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIArgs.cs
@@ -0,0 +1,16 @@
+using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
+
+namespace Ryujinx.HLE.HOS.Applets
+{
+    public struct SoftwareKeyboardUIArgs
+    {
+        public KeyboardMode KeyboardMode;
+        public string HeaderText;
+        public string SubtitleText;
+        public string InitialText;
+        public string GuideText;
+        public string SubmitText;
+        public int StringLengthMin;
+        public int StringLengthMax;
+    }
+}
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIState.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIState.cs
new file mode 100644
index 00000000..6199ff66
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUIState.cs
@@ -0,0 +1,22 @@
+using Ryujinx.HLE.UI;
+
+namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
+{
+    /// <summary>
+    /// TODO
+    /// </summary>
+    internal class SoftwareKeyboardUIState
+    {
+        public string InputText = "";
+        public int CursorBegin = 0;
+        public int CursorEnd = 0;
+        public bool AcceptPressed = false;
+        public bool CancelPressed = false;
+        public bool OverwriteMode = false;
+        public bool TypingEnabled = true;
+        public bool ControllerEnabled = true;
+        public int TextBoxBlinkCounter = 0;
+
+        public RenderingSurfaceInfo SurfaceInfo = null;
+    }
+}
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs
deleted file mode 100644
index 52fa7ed8..00000000
--- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
-
-namespace Ryujinx.HLE.HOS.Applets
-{
-    public struct SoftwareKeyboardUiArgs
-    {
-        public KeyboardMode KeyboardMode;
-        public string HeaderText;
-        public string SubtitleText;
-        public string InitialText;
-        public string GuideText;
-        public string SubmitText;
-        public int StringLengthMin;
-        public int StringLengthMax;
-    }
-}
diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiState.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiState.cs
deleted file mode 100644
index 608d51f3..00000000
--- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiState.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Ryujinx.HLE.Ui;
-
-namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
-{
-    /// <summary>
-    /// TODO
-    /// </summary>
-    internal class SoftwareKeyboardUiState
-    {
-        public string InputText = "";
-        public int CursorBegin = 0;
-        public int CursorEnd = 0;
-        public bool AcceptPressed = false;
-        public bool CancelPressed = false;
-        public bool OverwriteMode = false;
-        public bool TypingEnabled = true;
-        public bool ControllerEnabled = true;
-        public int TextBoxBlinkCounter = 0;
-
-        public RenderingSurfaceInfo SurfaceInfo = null;
-    }
-}
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
index 271d0060..9a7fdcc1 100644
--- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
@@ -97,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
 
             if (titleId == 0)
             {
-                context.Device.UiHandler.ExecuteProgram(context.Device, ProgramSpecifyKind.RestartProgram, titleId);
+                context.Device.UIHandler.ExecuteProgram(context.Device, ProgramSpecifyKind.RestartProgram, titleId);
             }
             else
             {
@@ -524,7 +524,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
 
             Logger.Stub?.PrintStub(LogClass.ServiceAm, new { kind, value });
 
-            context.Device.UiHandler.ExecuteProgram(context.Device, kind, value);
+            context.Device.UIHandler.ExecuteProgram(context.Device, kind, value);
 
             return ResultCode.Success;
         }
diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs
index 143e2166..b6988f08 100644
--- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs
@@ -7,7 +7,7 @@ using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
 using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService;
 using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService.Types;
 using Ryujinx.HLE.HOS.Services.Vi.Types;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Horizon.Common;
 using System;
 using System.Collections.Generic;
diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs
index ae063a47..498714dc 100644
--- a/src/Ryujinx.HLE/Switch.cs
+++ b/src/Ryujinx.HLE/Switch.cs
@@ -7,7 +7,7 @@ using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Apm;
 using Ryujinx.HLE.HOS.Services.Hid;
 using Ryujinx.HLE.Loaders.Processes;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Memory;
 using System;
 
@@ -25,7 +25,7 @@ namespace Ryujinx.HLE
         public PerformanceStatistics Statistics { get; }
         public Hid Hid { get; }
         public TamperMachine TamperMachine { get; }
-        public IHostUiHandler UiHandler { get; }
+        public IHostUIHandler UIHandler { get; }
 
         public bool EnableDeviceVsync { get; set; } = true;
 
@@ -39,7 +39,7 @@ namespace Ryujinx.HLE
 
             Configuration = configuration;
             FileSystem = Configuration.VirtualFileSystem;
-            UiHandler = Configuration.HostUiHandler;
+            UIHandler = Configuration.HostUIHandler;
 
             MemoryAllocationFlags memoryAllocationFlags = configuration.MemoryManagerMode == MemoryManagerMode.SoftwarePageTable
                 ? MemoryAllocationFlags.Reserve
diff --git a/src/Ryujinx.HLE/UI/DynamicTextChangedHandler.cs b/src/Ryujinx.HLE/UI/DynamicTextChangedHandler.cs
new file mode 100644
index 00000000..c0945259
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/DynamicTextChangedHandler.cs
@@ -0,0 +1,4 @@
+namespace Ryujinx.HLE.UI
+{
+    public delegate void DynamicTextChangedHandler(string text, int cursorBegin, int cursorEnd, bool overwriteMode);
+}
diff --git a/src/Ryujinx.HLE/UI/IDynamicTextInputHandler.cs b/src/Ryujinx.HLE/UI/IDynamicTextInputHandler.cs
new file mode 100644
index 00000000..1ff451d1
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/IDynamicTextInputHandler.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Ryujinx.HLE.UI
+{
+    public interface IDynamicTextInputHandler : IDisposable
+    {
+        event DynamicTextChangedHandler TextChangedEvent;
+        event KeyPressedHandler KeyPressedEvent;
+        event KeyReleasedHandler KeyReleasedEvent;
+
+        bool TextProcessingEnabled { get; set; }
+
+        void SetText(string text, int cursorBegin);
+        void SetText(string text, int cursorBegin, int cursorEnd);
+    }
+}
diff --git a/src/Ryujinx.HLE/UI/IHostUIHandler.cs b/src/Ryujinx.HLE/UI/IHostUIHandler.cs
new file mode 100644
index 00000000..3b3a430e
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/IHostUIHandler.cs
@@ -0,0 +1,51 @@
+using Ryujinx.HLE.HOS.Applets;
+using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
+
+namespace Ryujinx.HLE.UI
+{
+    public interface IHostUIHandler
+    {
+        /// <summary>
+        /// Displays an Input Dialog box to the user and blocks until text is entered.
+        /// </summary>
+        /// <param name="userText">Text that the user entered. Set to `null` on internal errors</param>
+        /// <returns>True when OK is pressed, False otherwise. Also returns True on internal errors</returns>
+        bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText);
+
+        /// <summary>
+        /// Displays a Message Dialog box to the user and blocks until it is closed.
+        /// </summary>
+        /// <returns>True when OK is pressed, False otherwise.</returns>
+        bool DisplayMessageDialog(string title, string message);
+
+        /// <summary>
+        /// Displays a Message Dialog box specific to Controller Applet and blocks until it is closed.
+        /// </summary>
+        /// <returns>True when OK is pressed, False otherwise.</returns>
+        bool DisplayMessageDialog(ControllerAppletUIArgs args);
+
+        /// <summary>
+        /// Tell the UI that we need to transisition to another program.
+        /// </summary>
+        /// <param name="device">The device instance.</param>
+        /// <param name="kind">The program kind.</param>
+        /// <param name="value">The value associated to the <paramref name="kind"/>.</param>
+        void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value);
+
+        /// Displays a Message Dialog box specific to Error Applet and blocks until it is closed.
+        /// </summary>
+        /// <returns>False when OK is pressed, True when another button (Details) is pressed.</returns>
+        bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText);
+
+        /// <summary>
+        /// Creates a handler to process keyboard inputs into text strings.
+        /// </summary>
+        /// <returns>An instance of the text handler.</returns>
+        IDynamicTextInputHandler CreateDynamicTextInputHandler();
+
+        /// <summary>
+        /// Gets fonts and colors used by the host.
+        /// </summary>
+        IHostUITheme HostUITheme { get; }
+    }
+}
diff --git a/src/Ryujinx.HLE/UI/IHostUITheme.cs b/src/Ryujinx.HLE/UI/IHostUITheme.cs
new file mode 100644
index 00000000..3b054400
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/IHostUITheme.cs
@@ -0,0 +1,13 @@
+namespace Ryujinx.HLE.UI
+{
+    public interface IHostUITheme
+    {
+        string FontFamily { get; }
+
+        ThemeColor DefaultBackgroundColor { get; }
+        ThemeColor DefaultForegroundColor { get; }
+        ThemeColor DefaultBorderColor { get; }
+        ThemeColor SelectionBackgroundColor { get; }
+        ThemeColor SelectionForegroundColor { get; }
+    }
+}
diff --git a/src/Ryujinx.HLE/UI/Input/NpadButtonHandler.cs b/src/Ryujinx.HLE/UI/Input/NpadButtonHandler.cs
new file mode 100644
index 00000000..73c30661
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/Input/NpadButtonHandler.cs
@@ -0,0 +1,6 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
+
+namespace Ryujinx.HLE.UI.Input
+{
+    delegate void NpadButtonHandler(int npadIndex, NpadButton button);
+}
diff --git a/src/Ryujinx.HLE/UI/Input/NpadReader.cs b/src/Ryujinx.HLE/UI/Input/NpadReader.cs
new file mode 100644
index 00000000..8276d616
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/Input/NpadReader.cs
@@ -0,0 +1,140 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
+
+namespace Ryujinx.HLE.UI.Input
+{
+    /// <summary>
+    /// Class that converts Hid entries for the Npad into pressed / released events.
+    /// </summary>
+    class NpadReader
+    {
+        private readonly Switch _device;
+        private readonly NpadCommonState[] _lastStates;
+
+        public event NpadButtonHandler NpadButtonUpEvent;
+        public event NpadButtonHandler NpadButtonDownEvent;
+
+        public NpadReader(Switch device)
+        {
+            _device = device;
+            _lastStates = new NpadCommonState[_device.Hid.SharedMemory.Npads.Length];
+        }
+
+        public NpadButton GetCurrentButtonsOfNpad(int npadIndex)
+        {
+            return _lastStates[npadIndex].Buttons;
+        }
+
+        public NpadButton GetCurrentButtonsOfAllNpads()
+        {
+            NpadButton buttons = 0;
+
+            foreach (var state in _lastStates)
+            {
+                buttons |= state.Buttons;
+            }
+
+            return buttons;
+        }
+
+        private static ref RingLifo<NpadCommonState> GetCommonStateLifo(ref NpadInternalState npad)
+        {
+            switch (npad.StyleSet)
+            {
+                case NpadStyleTag.FullKey:
+                    return ref npad.FullKey;
+                case NpadStyleTag.Handheld:
+                    return ref npad.Handheld;
+                case NpadStyleTag.JoyDual:
+                    return ref npad.JoyDual;
+                case NpadStyleTag.JoyLeft:
+                    return ref npad.JoyLeft;
+                case NpadStyleTag.JoyRight:
+                    return ref npad.JoyRight;
+                case NpadStyleTag.Palma:
+                    return ref npad.Palma;
+                default:
+                    return ref npad.SystemExt;
+            }
+        }
+
+        public void Update(bool supressEvents = false)
+        {
+            ref var npads = ref _device.Hid.SharedMemory.Npads;
+
+            // Process each input individually.
+            for (int npadIndex = 0; npadIndex < npads.Length; npadIndex++)
+            {
+                UpdateNpad(npadIndex, supressEvents);
+            }
+        }
+
+        private void UpdateNpad(int npadIndex, bool supressEvents)
+        {
+            const int MaxEntries = 1024;
+
+            ref var npadState = ref _device.Hid.SharedMemory.Npads[npadIndex];
+            ref var lastEntry = ref _lastStates[npadIndex];
+
+            var fullKeyEntries = GetCommonStateLifo(ref npadState.InternalState).ReadEntries(MaxEntries);
+
+            int firstEntryNum;
+
+            // Scan the LIFO for the first entry that is newer that what's already processed.
+            for (firstEntryNum = fullKeyEntries.Length - 1;
+                 firstEntryNum >= 0 && fullKeyEntries[firstEntryNum].Object.SamplingNumber <= lastEntry.SamplingNumber;
+                 firstEntryNum--)
+            {
+            }
+
+            if (firstEntryNum == -1)
+            {
+                return;
+            }
+
+            for (; firstEntryNum >= 0; firstEntryNum--)
+            {
+                var entry = fullKeyEntries[firstEntryNum];
+
+                // The interval of valid entries should be contiguous.
+                if (entry.SamplingNumber < lastEntry.SamplingNumber)
+                {
+                    break;
+                }
+
+                if (!supressEvents)
+                {
+                    ProcessNpadButtons(npadIndex, entry.Object.Buttons);
+                }
+
+                lastEntry = entry.Object;
+            }
+        }
+
+        private void ProcessNpadButtons(int npadIndex, NpadButton buttons)
+        {
+            NpadButton lastButtons = _lastStates[npadIndex].Buttons;
+
+            for (ulong buttonMask = 1; buttonMask != 0; buttonMask <<= 1)
+            {
+                NpadButton currentButton = (NpadButton)buttonMask & buttons;
+                NpadButton lastButton = (NpadButton)buttonMask & lastButtons;
+
+                if (lastButton != 0)
+                {
+                    if (currentButton == 0)
+                    {
+                        NpadButtonUpEvent?.Invoke(npadIndex, lastButton);
+                    }
+                }
+                else
+                {
+                    if (currentButton != 0)
+                    {
+                        NpadButtonDownEvent?.Invoke(npadIndex, currentButton);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.HLE/UI/KeyPressedHandler.cs b/src/Ryujinx.HLE/UI/KeyPressedHandler.cs
new file mode 100644
index 00000000..6feb11bd
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/KeyPressedHandler.cs
@@ -0,0 +1,6 @@
+using Ryujinx.Common.Configuration.Hid;
+
+namespace Ryujinx.HLE.UI
+{
+    public delegate bool KeyPressedHandler(Key key);
+}
diff --git a/src/Ryujinx.HLE/UI/KeyReleasedHandler.cs b/src/Ryujinx.HLE/UI/KeyReleasedHandler.cs
new file mode 100644
index 00000000..3de89d0c
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/KeyReleasedHandler.cs
@@ -0,0 +1,6 @@
+using Ryujinx.Common.Configuration.Hid;
+
+namespace Ryujinx.HLE.UI
+{
+    public delegate bool KeyReleasedHandler(Key key);
+}
diff --git a/src/Ryujinx.HLE/UI/RenderingSurfaceInfo.cs b/src/Ryujinx.HLE/UI/RenderingSurfaceInfo.cs
new file mode 100644
index 00000000..af0a0d44
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/RenderingSurfaceInfo.cs
@@ -0,0 +1,45 @@
+using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
+using System;
+
+namespace Ryujinx.HLE.UI
+{
+    /// <summary>
+    /// Information about the indirect layer that is being drawn to.
+    /// </summary>
+    class RenderingSurfaceInfo : IEquatable<RenderingSurfaceInfo>
+    {
+        public ColorFormat ColorFormat { get; }
+        public uint Width { get; }
+        public uint Height { get; }
+        public uint Pitch { get; }
+        public uint Size { get; }
+
+        public RenderingSurfaceInfo(ColorFormat colorFormat, uint width, uint height, uint pitch, uint size)
+        {
+            ColorFormat = colorFormat;
+            Width = width;
+            Height = height;
+            Pitch = pitch;
+            Size = size;
+        }
+
+        public bool Equals(RenderingSurfaceInfo other)
+        {
+            return ColorFormat == other.ColorFormat &&
+                   Width == other.Width &&
+                   Height == other.Height &&
+                   Pitch == other.Pitch &&
+                   Size == other.Size;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return obj is RenderingSurfaceInfo info && Equals(info);
+        }
+
+        public override int GetHashCode()
+        {
+            return BitConverter.ToInt32(BitConverter.GetBytes(((ulong)ColorFormat) ^ Width ^ Height ^ Pitch ^ Size));
+        }
+    }
+}
diff --git a/src/Ryujinx.HLE/UI/ThemeColor.cs b/src/Ryujinx.HLE/UI/ThemeColor.cs
new file mode 100644
index 00000000..c5cfb147
--- /dev/null
+++ b/src/Ryujinx.HLE/UI/ThemeColor.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.HLE.UI
+{
+    public readonly struct ThemeColor
+    {
+        public float A { get; }
+        public float R { get; }
+        public float G { get; }
+        public float B { get; }
+
+        public ThemeColor(float a, float r, float g, float b)
+        {
+            A = a;
+            R = r;
+            G = g;
+            B = b;
+        }
+    }
+}
diff --git a/src/Ryujinx.HLE/Ui/DynamicTextChangedHandler.cs b/src/Ryujinx.HLE/Ui/DynamicTextChangedHandler.cs
deleted file mode 100644
index cb9ca0de..00000000
--- a/src/Ryujinx.HLE/Ui/DynamicTextChangedHandler.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace Ryujinx.HLE.Ui
-{
-    public delegate void DynamicTextChangedHandler(string text, int cursorBegin, int cursorEnd, bool overwriteMode);
-}
diff --git a/src/Ryujinx.HLE/Ui/IDynamicTextInputHandler.cs b/src/Ryujinx.HLE/Ui/IDynamicTextInputHandler.cs
deleted file mode 100644
index e530d2c4..00000000
--- a/src/Ryujinx.HLE/Ui/IDynamicTextInputHandler.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace Ryujinx.HLE.Ui
-{
-    public interface IDynamicTextInputHandler : IDisposable
-    {
-        event DynamicTextChangedHandler TextChangedEvent;
-        event KeyPressedHandler KeyPressedEvent;
-        event KeyReleasedHandler KeyReleasedEvent;
-
-        bool TextProcessingEnabled { get; set; }
-
-        void SetText(string text, int cursorBegin);
-        void SetText(string text, int cursorBegin, int cursorEnd);
-    }
-}
diff --git a/src/Ryujinx.HLE/Ui/IHostUiHandler.cs b/src/Ryujinx.HLE/Ui/IHostUiHandler.cs
deleted file mode 100644
index 68f78f22..00000000
--- a/src/Ryujinx.HLE/Ui/IHostUiHandler.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Ryujinx.HLE.HOS.Applets;
-using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
-
-namespace Ryujinx.HLE.Ui
-{
-    public interface IHostUiHandler
-    {
-        /// <summary>
-        /// Displays an Input Dialog box to the user and blocks until text is entered.
-        /// </summary>
-        /// <param name="userText">Text that the user entered. Set to `null` on internal errors</param>
-        /// <returns>True when OK is pressed, False otherwise. Also returns True on internal errors</returns>
-        bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText);
-
-        /// <summary>
-        /// Displays a Message Dialog box to the user and blocks until it is closed.
-        /// </summary>
-        /// <returns>True when OK is pressed, False otherwise.</returns>
-        bool DisplayMessageDialog(string title, string message);
-
-        /// <summary>
-        /// Displays a Message Dialog box specific to Controller Applet and blocks until it is closed.
-        /// </summary>
-        /// <returns>True when OK is pressed, False otherwise.</returns>
-        bool DisplayMessageDialog(ControllerAppletUiArgs args);
-
-        /// <summary>
-        /// Tell the UI that we need to transisition to another program.
-        /// </summary>
-        /// <param name="device">The device instance.</param>
-        /// <param name="kind">The program kind.</param>
-        /// <param name="value">The value associated to the <paramref name="kind"/>.</param>
-        void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value);
-
-        /// Displays a Message Dialog box specific to Error Applet and blocks until it is closed.
-        /// </summary>
-        /// <returns>False when OK is pressed, True when another button (Details) is pressed.</returns>
-        bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText);
-
-        /// <summary>
-        /// Creates a handler to process keyboard inputs into text strings.
-        /// </summary>
-        /// <returns>An instance of the text handler.</returns>
-        IDynamicTextInputHandler CreateDynamicTextInputHandler();
-
-        /// <summary>
-        /// Gets fonts and colors used by the host.
-        /// </summary>
-        IHostUiTheme HostUiTheme { get; }
-    }
-}
diff --git a/src/Ryujinx.HLE/Ui/IHostUiTheme.cs b/src/Ryujinx.HLE/Ui/IHostUiTheme.cs
deleted file mode 100644
index 11d82361..00000000
--- a/src/Ryujinx.HLE/Ui/IHostUiTheme.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Ryujinx.HLE.Ui
-{
-    public interface IHostUiTheme
-    {
-        string FontFamily { get; }
-
-        ThemeColor DefaultBackgroundColor { get; }
-        ThemeColor DefaultForegroundColor { get; }
-        ThemeColor DefaultBorderColor { get; }
-        ThemeColor SelectionBackgroundColor { get; }
-        ThemeColor SelectionForegroundColor { get; }
-    }
-}
diff --git a/src/Ryujinx.HLE/Ui/Input/NpadButtonHandler.cs b/src/Ryujinx.HLE/Ui/Input/NpadButtonHandler.cs
deleted file mode 100644
index 2d1c1c49..00000000
--- a/src/Ryujinx.HLE/Ui/Input/NpadButtonHandler.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
-
-namespace Ryujinx.HLE.Ui.Input
-{
-    delegate void NpadButtonHandler(int npadIndex, NpadButton button);
-}
diff --git a/src/Ryujinx.HLE/Ui/Input/NpadReader.cs b/src/Ryujinx.HLE/Ui/Input/NpadReader.cs
deleted file mode 100644
index 8fc95dc9..00000000
--- a/src/Ryujinx.HLE/Ui/Input/NpadReader.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
-using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
-
-namespace Ryujinx.HLE.Ui.Input
-{
-    /// <summary>
-    /// Class that converts Hid entries for the Npad into pressed / released events.
-    /// </summary>
-    class NpadReader
-    {
-        private readonly Switch _device;
-        private readonly NpadCommonState[] _lastStates;
-
-        public event NpadButtonHandler NpadButtonUpEvent;
-        public event NpadButtonHandler NpadButtonDownEvent;
-
-        public NpadReader(Switch device)
-        {
-            _device = device;
-            _lastStates = new NpadCommonState[_device.Hid.SharedMemory.Npads.Length];
-        }
-
-        public NpadButton GetCurrentButtonsOfNpad(int npadIndex)
-        {
-            return _lastStates[npadIndex].Buttons;
-        }
-
-        public NpadButton GetCurrentButtonsOfAllNpads()
-        {
-            NpadButton buttons = 0;
-
-            foreach (var state in _lastStates)
-            {
-                buttons |= state.Buttons;
-            }
-
-            return buttons;
-        }
-
-        private static ref RingLifo<NpadCommonState> GetCommonStateLifo(ref NpadInternalState npad)
-        {
-            switch (npad.StyleSet)
-            {
-                case NpadStyleTag.FullKey:
-                    return ref npad.FullKey;
-                case NpadStyleTag.Handheld:
-                    return ref npad.Handheld;
-                case NpadStyleTag.JoyDual:
-                    return ref npad.JoyDual;
-                case NpadStyleTag.JoyLeft:
-                    return ref npad.JoyLeft;
-                case NpadStyleTag.JoyRight:
-                    return ref npad.JoyRight;
-                case NpadStyleTag.Palma:
-                    return ref npad.Palma;
-                default:
-                    return ref npad.SystemExt;
-            }
-        }
-
-        public void Update(bool supressEvents = false)
-        {
-            ref var npads = ref _device.Hid.SharedMemory.Npads;
-
-            // Process each input individually.
-            for (int npadIndex = 0; npadIndex < npads.Length; npadIndex++)
-            {
-                UpdateNpad(npadIndex, supressEvents);
-            }
-        }
-
-        private void UpdateNpad(int npadIndex, bool supressEvents)
-        {
-            const int MaxEntries = 1024;
-
-            ref var npadState = ref _device.Hid.SharedMemory.Npads[npadIndex];
-            ref var lastEntry = ref _lastStates[npadIndex];
-
-            var fullKeyEntries = GetCommonStateLifo(ref npadState.InternalState).ReadEntries(MaxEntries);
-
-            int firstEntryNum;
-
-            // Scan the LIFO for the first entry that is newer that what's already processed.
-            for (firstEntryNum = fullKeyEntries.Length - 1;
-                 firstEntryNum >= 0 && fullKeyEntries[firstEntryNum].Object.SamplingNumber <= lastEntry.SamplingNumber;
-                 firstEntryNum--)
-            {
-            }
-
-            if (firstEntryNum == -1)
-            {
-                return;
-            }
-
-            for (; firstEntryNum >= 0; firstEntryNum--)
-            {
-                var entry = fullKeyEntries[firstEntryNum];
-
-                // The interval of valid entries should be contiguous.
-                if (entry.SamplingNumber < lastEntry.SamplingNumber)
-                {
-                    break;
-                }
-
-                if (!supressEvents)
-                {
-                    ProcessNpadButtons(npadIndex, entry.Object.Buttons);
-                }
-
-                lastEntry = entry.Object;
-            }
-        }
-
-        private void ProcessNpadButtons(int npadIndex, NpadButton buttons)
-        {
-            NpadButton lastButtons = _lastStates[npadIndex].Buttons;
-
-            for (ulong buttonMask = 1; buttonMask != 0; buttonMask <<= 1)
-            {
-                NpadButton currentButton = (NpadButton)buttonMask & buttons;
-                NpadButton lastButton = (NpadButton)buttonMask & lastButtons;
-
-                if (lastButton != 0)
-                {
-                    if (currentButton == 0)
-                    {
-                        NpadButtonUpEvent?.Invoke(npadIndex, lastButton);
-                    }
-                }
-                else
-                {
-                    if (currentButton != 0)
-                    {
-                        NpadButtonDownEvent?.Invoke(npadIndex, currentButton);
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.HLE/Ui/KeyPressedHandler.cs b/src/Ryujinx.HLE/Ui/KeyPressedHandler.cs
deleted file mode 100644
index 31e75437..00000000
--- a/src/Ryujinx.HLE/Ui/KeyPressedHandler.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using Ryujinx.Common.Configuration.Hid;
-
-namespace Ryujinx.HLE.Ui
-{
-    public delegate bool KeyPressedHandler(Key key);
-}
diff --git a/src/Ryujinx.HLE/Ui/KeyReleasedHandler.cs b/src/Ryujinx.HLE/Ui/KeyReleasedHandler.cs
deleted file mode 100644
index d5b6d201..00000000
--- a/src/Ryujinx.HLE/Ui/KeyReleasedHandler.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using Ryujinx.Common.Configuration.Hid;
-
-namespace Ryujinx.HLE.Ui
-{
-    public delegate bool KeyReleasedHandler(Key key);
-}
diff --git a/src/Ryujinx.HLE/Ui/RenderingSurfaceInfo.cs b/src/Ryujinx.HLE/Ui/RenderingSurfaceInfo.cs
deleted file mode 100644
index 0b3d0a90..00000000
--- a/src/Ryujinx.HLE/Ui/RenderingSurfaceInfo.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
-using System;
-
-namespace Ryujinx.HLE.Ui
-{
-    /// <summary>
-    /// Information about the indirect layer that is being drawn to.
-    /// </summary>
-    class RenderingSurfaceInfo : IEquatable<RenderingSurfaceInfo>
-    {
-        public ColorFormat ColorFormat { get; }
-        public uint Width { get; }
-        public uint Height { get; }
-        public uint Pitch { get; }
-        public uint Size { get; }
-
-        public RenderingSurfaceInfo(ColorFormat colorFormat, uint width, uint height, uint pitch, uint size)
-        {
-            ColorFormat = colorFormat;
-            Width = width;
-            Height = height;
-            Pitch = pitch;
-            Size = size;
-        }
-
-        public bool Equals(RenderingSurfaceInfo other)
-        {
-            return ColorFormat == other.ColorFormat &&
-                   Width == other.Width &&
-                   Height == other.Height &&
-                   Pitch == other.Pitch &&
-                   Size == other.Size;
-        }
-
-        public override bool Equals(object obj)
-        {
-            return obj is RenderingSurfaceInfo info && Equals(info);
-        }
-
-        public override int GetHashCode()
-        {
-            return BitConverter.ToInt32(BitConverter.GetBytes(((ulong)ColorFormat) ^ Width ^ Height ^ Pitch ^ Size));
-        }
-    }
-}
diff --git a/src/Ryujinx.HLE/Ui/ThemeColor.cs b/src/Ryujinx.HLE/Ui/ThemeColor.cs
deleted file mode 100644
index 23657ed2..00000000
--- a/src/Ryujinx.HLE/Ui/ThemeColor.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Ryujinx.HLE.Ui
-{
-    public readonly struct ThemeColor
-    {
-        public float A { get; }
-        public float R { get; }
-        public float G { get; }
-        public float B { get; }
-
-        public ThemeColor(float a, float r, float g, float b)
-        {
-            A = a;
-            R = r;
-            G = g;
-            B = b;
-        }
-    }
-}
diff --git a/src/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs b/src/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs
index aae01a0c..503874ff 100644
--- a/src/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs
+++ b/src/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs
@@ -1,4 +1,4 @@
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using System.Threading;
 using System.Threading.Tasks;
 
diff --git a/src/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs b/src/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs
index a2df6f3e..78cd43ae 100644
--- a/src/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs
+++ b/src/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs
@@ -1,8 +1,8 @@
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 
 namespace Ryujinx.Headless.SDL2
 {
-    internal class HeadlessHostUiTheme : IHostUiTheme
+    internal class HeadlessHostUiTheme : IHostUITheme
     {
         public string FontFamily => "sans-serif";
 
diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs
index b1f43dc2..8768913f 100644
--- a/src/Ryujinx.Headless.SDL2/WindowBase.cs
+++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs
@@ -7,7 +7,7 @@ using Ryujinx.Graphics.Gpu;
 using Ryujinx.Graphics.OpenGL;
 using Ryujinx.HLE.HOS.Applets;
 using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
-using Ryujinx.HLE.Ui;
+using Ryujinx.HLE.UI;
 using Ryujinx.Input;
 using Ryujinx.Input.HLE;
 using Ryujinx.SDL2.Common;
@@ -25,7 +25,7 @@ using Switch = Ryujinx.HLE.Switch;
 
 namespace Ryujinx.Headless.SDL2
 {
-    abstract partial class WindowBase : IHostUiHandler, IDisposable
+    abstract partial class WindowBase : IHostUIHandler, IDisposable
     {
         protected const int DefaultWidth = 1280;
         protected const int DefaultHeight = 720;
@@ -53,7 +53,7 @@ namespace Ryujinx.Headless.SDL2
 
         protected IntPtr WindowHandle { get; set; }
 
-        public IHostUiTheme HostUiTheme { get; }
+        public IHostUITheme HostUITheme { get; }
         public int Width { get; private set; }
         public int Height { get; private set; }
         public int DisplayId { get; set; }
@@ -106,7 +106,7 @@ namespace Ryujinx.Headless.SDL2
             _gpuDoneEvent = new ManualResetEvent(false);
             _aspectRatio = aspectRatio;
             _enableMouse = enableMouse;
-            HostUiTheme = new HeadlessHostUiTheme();
+            HostUITheme = new HeadlessHostUiTheme();
 
             SDL2Driver.Instance.Initialize();
         }
@@ -465,7 +465,7 @@ namespace Ryujinx.Headless.SDL2
             Exit();
         }
 
-        public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
+        public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
         {
             // SDL2 doesn't support input dialogs
             userText = "Ryujinx";
@@ -480,7 +480,7 @@ namespace Ryujinx.Headless.SDL2
             return true;
         }
 
-        public bool DisplayMessageDialog(ControllerAppletUiArgs args)
+        public bool DisplayMessageDialog(ControllerAppletUIArgs args)
         {
             string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
 
diff --git a/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs b/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs
new file mode 100644
index 00000000..58e066b9
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Ryujinx.UI.App.Common
+{
+    public class ApplicationAddedEventArgs : EventArgs
+    {
+        public ApplicationData AppData { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs b/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs
new file mode 100644
index 00000000..5ed7baf1
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Ryujinx.UI.App.Common
+{
+    public class ApplicationCountUpdatedEventArgs : EventArgs
+    {
+        public int NumAppsFound { get; set; }
+        public int NumAppsLoaded { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/App/ApplicationData.cs b/src/Ryujinx.UI.Common/App/ApplicationData.cs
new file mode 100644
index 00000000..8cc7238e
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationData.cs
@@ -0,0 +1,158 @@
+using LibHac.Common;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.FsSystem;
+using LibHac.Loader;
+using LibHac.Ns;
+using LibHac.Tools.Fs;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.UI.Common.Helper;
+using System;
+using System.IO;
+
+namespace Ryujinx.UI.App.Common
+{
+    public class ApplicationData
+    {
+        public bool Favorite { get; set; }
+        public byte[] Icon { get; set; }
+        public string TitleName { get; set; }
+        public string TitleId { get; set; }
+        public string Developer { get; set; }
+        public string Version { get; set; }
+        public TimeSpan TimePlayed { get; set; }
+        public DateTime? LastPlayed { get; set; }
+        public string FileExtension { get; set; }
+        public long FileSize { get; set; }
+        public string Path { get; set; }
+        public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
+
+        public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
+
+        public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed);
+
+        public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
+
+        public static string GetApplicationBuildId(VirtualFileSystem virtualFileSystem, string titleFilePath)
+        {
+            using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
+
+            Nca mainNca = null;
+            Nca patchNca = null;
+
+            if (!System.IO.Path.Exists(titleFilePath))
+            {
+                Logger.Error?.Print(LogClass.Application, $"File does not exists. {titleFilePath}");
+                return string.Empty;
+            }
+
+            string extension = System.IO.Path.GetExtension(titleFilePath).ToLower();
+
+            if (extension is ".nsp" or ".xci")
+            {
+                IFileSystem pfs;
+
+                if (extension == ".xci")
+                {
+                    Xci xci = new(virtualFileSystem.KeySet, file.AsStorage());
+
+                    pfs = xci.OpenPartition(XciPartitionType.Secure);
+                }
+                else
+                {
+                    var pfsTemp = new PartitionFileSystem();
+                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                    pfs = pfsTemp;
+                }
+
+                foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
+                {
+                    using var ncaFile = new UniqueRef<IFile>();
+
+                    pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                    Nca nca = new(virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
+
+                    if (nca.Header.ContentType != NcaContentType.Program)
+                    {
+                        continue;
+                    }
+
+                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
+
+                    if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
+                    {
+                        patchNca = nca;
+                    }
+                    else
+                    {
+                        mainNca = nca;
+                    }
+                }
+            }
+            else if (extension == ".nca")
+            {
+                mainNca = new Nca(virtualFileSystem.KeySet, file.AsStorage());
+            }
+
+            if (mainNca == null)
+            {
+                Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file");
+
+                return string.Empty;
+            }
+
+            (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _);
+
+            if (updatePatchNca != null)
+            {
+                patchNca = updatePatchNca;
+            }
+
+            IFileSystem codeFs = null;
+
+            if (patchNca == null)
+            {
+                if (mainNca.CanOpenSection(NcaSectionType.Code))
+                {
+                    codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
+                }
+            }
+            else
+            {
+                if (patchNca.CanOpenSection(NcaSectionType.Code))
+                {
+                    codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
+                }
+            }
+
+            if (codeFs == null)
+            {
+                Logger.Error?.Print(LogClass.Loader, "No ExeFS found in NCA");
+
+                return string.Empty;
+            }
+
+            const string MainExeFs = "main";
+
+            if (!codeFs.FileExists($"/{MainExeFs}"))
+            {
+                Logger.Error?.Print(LogClass.Loader, "No main binary ExeFS found in ExeFS");
+
+                return string.Empty;
+            }
+
+            using var nsoFile = new UniqueRef<IFile>();
+
+            codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+            NsoReader reader = new();
+            reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
+
+            return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs b/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs
new file mode 100644
index 00000000..ada7cc34
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.App.Common
+{
+    [JsonSourceGenerationOptions(WriteIndented = true)]
+    [JsonSerializable(typeof(ApplicationMetadata))]
+    internal partial class ApplicationJsonSerializerContext : JsonSerializerContext
+    {
+    }
+}
diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs
new file mode 100644
index 00000000..65cf7a9e
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs
@@ -0,0 +1,930 @@
+using LibHac;
+using LibHac.Common;
+using LibHac.Common.Keys;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.FsSystem;
+using LibHac.Ns;
+using LibHac.Tools.Fs;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS.SystemState;
+using Ryujinx.HLE.Loaders.Npdm;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Configuration.System;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using Path = System.IO.Path;
+using TimeSpan = System.TimeSpan;
+
+namespace Ryujinx.UI.App.Common
+{
+    public class ApplicationLibrary
+    {
+        public event EventHandler<ApplicationAddedEventArgs> ApplicationAdded;
+        public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
+
+        private readonly byte[] _nspIcon;
+        private readonly byte[] _xciIcon;
+        private readonly byte[] _ncaIcon;
+        private readonly byte[] _nroIcon;
+        private readonly byte[] _nsoIcon;
+
+        private readonly VirtualFileSystem _virtualFileSystem;
+        private Language _desiredTitleLanguage;
+        private CancellationTokenSource _cancellationToken;
+
+        private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+        public ApplicationLibrary(VirtualFileSystem virtualFileSystem)
+        {
+            _virtualFileSystem = virtualFileSystem;
+
+            _nspIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSP.png");
+            _xciIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_XCI.png");
+            _ncaIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NCA.png");
+            _nroIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NRO.png");
+            _nsoIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSO.png");
+        }
+
+        private static byte[] GetResourceBytes(string resourceName)
+        {
+            Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
+            byte[] resourceByteArray = new byte[resourceStream.Length];
+
+            resourceStream.Read(resourceByteArray);
+
+            return resourceByteArray;
+        }
+
+        public void CancelLoading()
+        {
+            _cancellationToken?.Cancel();
+        }
+
+        public static void ReadControlData(IFileSystem controlFs, Span<byte> outProperty)
+        {
+            using UniqueRef<IFile> controlFile = new();
+
+            controlFs.OpenFile(ref controlFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
+            controlFile.Get.Read(out _, 0, outProperty, ReadOption.None).ThrowIfFailure();
+        }
+
+        public void LoadApplications(List<string> appDirs, Language desiredTitleLanguage)
+        {
+            int numApplicationsFound = 0;
+            int numApplicationsLoaded = 0;
+
+            _desiredTitleLanguage = desiredTitleLanguage;
+
+            _cancellationToken = new CancellationTokenSource();
+
+            // Builds the applications list with paths to found applications
+            List<string> applications = new();
+
+            try
+            {
+                foreach (string appDir in appDirs)
+                {
+                    if (_cancellationToken.Token.IsCancellationRequested)
+                    {
+                        return;
+                    }
+
+                    if (!Directory.Exists(appDir))
+                    {
+                        Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid directory: \"{appDir}\"");
+
+                        continue;
+                    }
+
+                    try
+                    {
+                        IEnumerable<string> files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file =>
+                        {
+                            return
+                            (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value) ||
+                            (Path.GetExtension(file).ToLower() is ".pfs0" && ConfigurationState.Instance.UI.ShownFileTypes.PFS0.Value) ||
+                            (Path.GetExtension(file).ToLower() is ".xci" && ConfigurationState.Instance.UI.ShownFileTypes.XCI.Value) ||
+                            (Path.GetExtension(file).ToLower() is ".nca" && ConfigurationState.Instance.UI.ShownFileTypes.NCA.Value) ||
+                            (Path.GetExtension(file).ToLower() is ".nro" && ConfigurationState.Instance.UI.ShownFileTypes.NRO.Value) ||
+                            (Path.GetExtension(file).ToLower() is ".nso" && ConfigurationState.Instance.UI.ShownFileTypes.NSO.Value);
+                        });
+
+                        foreach (string app in files)
+                        {
+                            if (_cancellationToken.Token.IsCancellationRequested)
+                            {
+                                return;
+                            }
+
+                            var fileInfo = new FileInfo(app);
+                            string extension = fileInfo.Extension.ToLower();
+
+                            if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden) && extension is ".nsp" or ".pfs0" or ".xci" or ".nca" or ".nro" or ".nso")
+                            {
+                                var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName;
+
+                                if (!File.Exists(fullPath))
+                                {
+                                    Logger.Warning?.Print(LogClass.Application, $"Skipping invalid symlink: {fileInfo.FullName}");
+                                    continue;
+                                }
+
+                                applications.Add(fullPath);
+                                numApplicationsFound++;
+                            }
+                        }
+                    }
+                    catch (UnauthorizedAccessException)
+                    {
+                        Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{appDir}\"");
+                    }
+                }
+
+                // Loops through applications list, creating a struct and then firing an event containing the struct for each application
+                foreach (string applicationPath in applications)
+                {
+                    if (_cancellationToken.Token.IsCancellationRequested)
+                    {
+                        return;
+                    }
+
+                    long fileSize = new FileInfo(applicationPath).Length;
+                    string titleName = "Unknown";
+                    string titleId = "0000000000000000";
+                    string developer = "Unknown";
+                    string version = "0";
+                    byte[] applicationIcon = null;
+
+                    BlitStruct<ApplicationControlProperty> controlHolder = new(1);
+
+                    try
+                    {
+                        string extension = Path.GetExtension(applicationPath).ToLower();
+
+                        using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read);
+
+                        if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
+                        {
+                            try
+                            {
+                                IFileSystem pfs;
+
+                                bool isExeFs = false;
+
+                                if (extension == ".xci")
+                                {
+                                    Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
+
+                                    pfs = xci.OpenPartition(XciPartitionType.Secure);
+                                }
+                                else
+                                {
+                                    var pfsTemp = new PartitionFileSystem();
+                                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                                    pfs = pfsTemp;
+
+                                    // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
+                                    bool hasMainNca = false;
+
+                                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
+                                    {
+                                        if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
+                                        {
+                                            using UniqueRef<IFile> ncaFile = new();
+
+                                            pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                                            Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
+                                            int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
+
+                                            // Some main NCAs don't have a data partition, so check if the partition exists before opening it
+                                            if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
+                                            {
+                                                hasMainNca = true;
+
+                                                break;
+                                            }
+                                        }
+                                        else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
+                                        {
+                                            isExeFs = true;
+                                        }
+                                    }
+
+                                    if (!hasMainNca && !isExeFs)
+                                    {
+                                        numApplicationsFound--;
+
+                                        continue;
+                                    }
+                                }
+
+                                if (isExeFs)
+                                {
+                                    applicationIcon = _nspIcon;
+
+                                    using UniqueRef<IFile> npdmFile = new();
+
+                                    Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read);
+
+                                    if (ResultFs.PathNotFound.Includes(result))
+                                    {
+                                        Npdm npdm = new(npdmFile.Get.AsStream());
+
+                                        titleName = npdm.TitleName;
+                                        titleId = npdm.Aci0.TitleId.ToString("x16");
+                                    }
+                                }
+                                else
+                                {
+                                    GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);
+
+                                    // Check if there is an update available.
+                                    if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs))
+                                    {
+                                        // Replace the original ControlFs by the updated one.
+                                        controlFs = updatedControlFs;
+                                    }
+
+                                    ReadControlData(controlFs, controlHolder.ByteSpan);
+
+                                    GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version);
+
+                                    // Read the icon from the ControlFS and store it as a byte array
+                                    try
+                                    {
+                                        using UniqueRef<IFile> icon = new();
+
+                                        controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                                        using MemoryStream stream = new();
+
+                                        icon.Get.AsStream().CopyTo(stream);
+                                        applicationIcon = stream.ToArray();
+                                    }
+                                    catch (HorizonResultException)
+                                    {
+                                        foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
+                                        {
+                                            if (entry.Name == "control.nacp")
+                                            {
+                                                continue;
+                                            }
+
+                                            using var icon = new UniqueRef<IFile>();
+
+                                            controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                                            using MemoryStream stream = new();
+
+                                            icon.Get.AsStream().CopyTo(stream);
+                                            applicationIcon = stream.ToArray();
+
+                                            if (applicationIcon != null)
+                                            {
+                                                break;
+                                            }
+                                        }
+
+                                        applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon;
+                                    }
+                                }
+                            }
+                            catch (MissingKeyException exception)
+                            {
+                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
+
+                                Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
+                            }
+                            catch (InvalidDataException)
+                            {
+                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
+
+                                Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
+                            }
+                            catch (Exception exception)
+                            {
+                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
+
+                                numApplicationsFound--;
+
+                                continue;
+                            }
+                        }
+                        else if (extension == ".nro")
+                        {
+                            BinaryReader reader = new(file);
+
+                            byte[] Read(long position, int size)
+                            {
+                                file.Seek(position, SeekOrigin.Begin);
+
+                                return reader.ReadBytes(size);
+                            }
+
+                            try
+                            {
+                                file.Seek(24, SeekOrigin.Begin);
+
+                                int assetOffset = reader.ReadInt32();
+
+                                if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
+                                {
+                                    byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
+
+                                    long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
+                                    long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
+
+                                    ulong nacpOffset = reader.ReadUInt64();
+                                    ulong nacpSize = reader.ReadUInt64();
+
+                                    // Reads and stores game icon as byte array
+                                    if (iconSize > 0)
+                                    {
+                                        applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);
+                                    }
+                                    else
+                                    {
+                                        applicationIcon = _nroIcon;
+                                    }
+
+                                    // Read the NACP data
+                                    Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);
+
+                                    GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version);
+                                }
+                                else
+                                {
+                                    applicationIcon = _nroIcon;
+                                    titleName = Path.GetFileNameWithoutExtension(applicationPath);
+                                }
+                            }
+                            catch
+                            {
+                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
+
+                                numApplicationsFound--;
+
+                                continue;
+                            }
+                        }
+                        else if (extension == ".nca")
+                        {
+                            try
+                            {
+                                Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
+                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
+
+                                if (nca.Header.ContentType != NcaContentType.Program || (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
+                                {
+                                    numApplicationsFound--;
+
+                                    continue;
+                                }
+                            }
+                            catch (InvalidDataException)
+                            {
+                                Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}");
+                            }
+                            catch
+                            {
+                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
+
+                                numApplicationsFound--;
+
+                                continue;
+                            }
+
+                            applicationIcon = _ncaIcon;
+                            titleName = Path.GetFileNameWithoutExtension(applicationPath);
+                        }
+                        // If its an NSO we just set defaults
+                        else if (extension == ".nso")
+                        {
+                            applicationIcon = _nsoIcon;
+                            titleName = Path.GetFileNameWithoutExtension(applicationPath);
+                        }
+                    }
+                    catch (IOException exception)
+                    {
+                        Logger.Warning?.Print(LogClass.Application, exception.Message);
+
+                        numApplicationsFound--;
+
+                        continue;
+                    }
+
+                    ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId, appMetadata =>
+                    {
+                        appMetadata.Title = titleName;
+
+                        // Only do the migration if time_played has a value and timespan_played hasn't been updated yet.
+                        if (appMetadata.TimePlayedOld != default && appMetadata.TimePlayed == TimeSpan.Zero)
+                        {
+                            appMetadata.TimePlayed = TimeSpan.FromSeconds(appMetadata.TimePlayedOld);
+                            appMetadata.TimePlayedOld = default;
+                        }
+
+                        // Only do the migration if last_played has a value and last_played_utc doesn't exist yet.
+                        if (appMetadata.LastPlayedOld != default && !appMetadata.LastPlayed.HasValue)
+                        {
+                            // Migrate from string-based last_played to DateTime-based last_played_utc.
+                            if (DateTime.TryParse(appMetadata.LastPlayedOld, out DateTime lastPlayedOldParsed))
+                            {
+                                appMetadata.LastPlayed = lastPlayedOldParsed;
+
+                                // Migration successful: deleting last_played from the metadata file.
+                                appMetadata.LastPlayedOld = default;
+                            }
+
+                        }
+                    });
+
+                    ApplicationData data = new()
+                    {
+                        Favorite = appMetadata.Favorite,
+                        Icon = applicationIcon,
+                        TitleName = titleName,
+                        TitleId = titleId,
+                        Developer = developer,
+                        Version = version,
+                        TimePlayed = appMetadata.TimePlayed,
+                        LastPlayed = appMetadata.LastPlayed,
+                        FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper(),
+                        FileSize = fileSize,
+                        Path = applicationPath,
+                        ControlHolder = controlHolder,
+                    };
+
+                    numApplicationsLoaded++;
+
+                    OnApplicationAdded(new ApplicationAddedEventArgs
+                    {
+                        AppData = data,
+                    });
+
+                    OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
+                    {
+                        NumAppsFound = numApplicationsFound,
+                        NumAppsLoaded = numApplicationsLoaded,
+                    });
+                }
+
+                OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
+                {
+                    NumAppsFound = numApplicationsFound,
+                    NumAppsLoaded = numApplicationsLoaded,
+                });
+            }
+            finally
+            {
+                _cancellationToken.Dispose();
+                _cancellationToken = null;
+            }
+        }
+
+        protected void OnApplicationAdded(ApplicationAddedEventArgs e)
+        {
+            ApplicationAdded?.Invoke(null, e);
+        }
+
+        protected void OnApplicationCountUpdated(ApplicationCountUpdatedEventArgs e)
+        {
+            ApplicationCountUpdated?.Invoke(null, e);
+        }
+
+        private void GetControlFsAndTitleId(IFileSystem pfs, out IFileSystem controlFs, out string titleId)
+        {
+            (_, _, Nca controlNca) = GetGameData(_virtualFileSystem, pfs, 0);
+
+            // Return the ControlFS
+            controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
+            titleId = controlNca?.Header.TitleId.ToString("x16");
+        }
+
+        public static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
+        {
+            string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui");
+            string metadataFile = Path.Combine(metadataFolder, "metadata.json");
+
+            ApplicationMetadata appMetadata;
+
+            if (!File.Exists(metadataFile))
+            {
+                Directory.CreateDirectory(metadataFolder);
+
+                appMetadata = new ApplicationMetadata();
+
+                JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
+            }
+
+            try
+            {
+                appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata);
+            }
+            catch (JsonException)
+            {
+                Logger.Warning?.Print(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults.");
+
+                appMetadata = new ApplicationMetadata();
+            }
+
+            if (modifyFunction != null)
+            {
+                modifyFunction(appMetadata);
+
+                JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
+            }
+
+            return appMetadata;
+        }
+
+        public byte[] GetApplicationIcon(string applicationPath, Language desiredTitleLanguage)
+        {
+            byte[] applicationIcon = null;
+
+            try
+            {
+                // Look for icon only if applicationPath is not a directory
+                if (!Directory.Exists(applicationPath))
+                {
+                    string extension = Path.GetExtension(applicationPath).ToLower();
+
+                    using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read);
+
+                    if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
+                    {
+                        try
+                        {
+                            IFileSystem pfs;
+
+                            bool isExeFs = false;
+
+                            if (extension == ".xci")
+                            {
+                                Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
+
+                                pfs = xci.OpenPartition(XciPartitionType.Secure);
+                            }
+                            else
+                            {
+                                var pfsTemp = new PartitionFileSystem();
+                                pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                                pfs = pfsTemp;
+
+                                foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
+                                {
+                                    if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
+                                    {
+                                        isExeFs = true;
+                                    }
+                                }
+                            }
+
+                            if (isExeFs)
+                            {
+                                applicationIcon = _nspIcon;
+                            }
+                            else
+                            {
+                                // Store the ControlFS in variable called controlFs
+                                GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out _);
+
+                                // Read the icon from the ControlFS and store it as a byte array
+                                try
+                                {
+                                    using var icon = new UniqueRef<IFile>();
+
+                                    controlFs.OpenFile(ref icon.Ref, $"/icon_{desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                                    using MemoryStream stream = new();
+
+                                    icon.Get.AsStream().CopyTo(stream);
+                                    applicationIcon = stream.ToArray();
+                                }
+                                catch (HorizonResultException)
+                                {
+                                    foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
+                                    {
+                                        if (entry.Name == "control.nacp")
+                                        {
+                                            continue;
+                                        }
+
+                                        using var icon = new UniqueRef<IFile>();
+
+                                        controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                                        using (MemoryStream stream = new())
+                                        {
+                                            icon.Get.AsStream().CopyTo(stream);
+                                            applicationIcon = stream.ToArray();
+                                        }
+
+                                        if (applicationIcon != null)
+                                        {
+                                            break;
+                                        }
+                                    }
+
+                                    applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon;
+                                }
+                            }
+                        }
+                        catch (MissingKeyException)
+                        {
+                            applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
+                        }
+                        catch (InvalidDataException)
+                        {
+                            applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
+                        }
+                        catch (Exception exception)
+                        {
+                            Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
+                        }
+                    }
+                    else if (extension == ".nro")
+                    {
+                        BinaryReader reader = new(file);
+
+                        byte[] Read(long position, int size)
+                        {
+                            file.Seek(position, SeekOrigin.Begin);
+
+                            return reader.ReadBytes(size);
+                        }
+
+                        try
+                        {
+                            file.Seek(24, SeekOrigin.Begin);
+
+                            int assetOffset = reader.ReadInt32();
+
+                            if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
+                            {
+                                byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
+
+                                long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
+                                long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
+
+                                // Reads and stores game icon as byte array
+                                if (iconSize > 0)
+                                {
+                                    applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);
+                                }
+                                else
+                                {
+                                    applicationIcon = _nroIcon;
+                                }
+                            }
+                            else
+                            {
+                                applicationIcon = _nroIcon;
+                            }
+                        }
+                        catch
+                        {
+                            Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
+                        }
+                    }
+                    else if (extension == ".nca")
+                    {
+                        applicationIcon = _ncaIcon;
+                    }
+                    // If its an NSO we just set defaults
+                    else if (extension == ".nso")
+                    {
+                        applicationIcon = _nsoIcon;
+                    }
+                }
+            }
+            catch (Exception)
+            {
+                Logger.Warning?.Print(LogClass.Application, $"Could not retrieve a valid icon for the app. Default icon will be used. Errored File: {applicationPath}");
+            }
+
+            return applicationIcon ?? _ncaIcon;
+        }
+
+        private void GetGameInformation(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher, out string version)
+        {
+            _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
+
+            if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
+            {
+                titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
+                publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
+            }
+            else
+            {
+                titleName = null;
+                publisher = null;
+            }
+
+            if (string.IsNullOrWhiteSpace(titleName))
+            {
+                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
+                {
+                    if (!controlTitle.NameString.IsEmpty())
+                    {
+                        titleName = controlTitle.NameString.ToString();
+
+                        break;
+                    }
+                }
+            }
+
+            if (string.IsNullOrWhiteSpace(publisher))
+            {
+                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
+                {
+                    if (!controlTitle.PublisherString.IsEmpty())
+                    {
+                        publisher = controlTitle.PublisherString.ToString();
+
+                        break;
+                    }
+                }
+            }
+
+            if (controlData.PresenceGroupId != 0)
+            {
+                titleId = controlData.PresenceGroupId.ToString("x16");
+            }
+            else if (controlData.SaveDataOwnerId != 0)
+            {
+                titleId = controlData.SaveDataOwnerId.ToString();
+            }
+            else if (controlData.AddOnContentBaseId != 0)
+            {
+                titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
+            }
+            else
+            {
+                titleId = "0000000000000000";
+            }
+
+            version = controlData.DisplayVersionString.ToString();
+        }
+
+        private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs)
+        {
+            updatedControlFs = null;
+
+            string updatePath = "(unknown)";
+
+            try
+            {
+                (Nca patchNca, Nca controlNca) = GetGameUpdateData(_virtualFileSystem, titleId, 0, out updatePath);
+
+                if (patchNca != null && controlNca != null)
+                {
+                    updatedControlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
+
+                    return true;
+                }
+            }
+            catch (InvalidDataException)
+            {
+                Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {updatePath}");
+            }
+            catch (MissingKeyException exception)
+            {
+                Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}");
+            }
+
+            return false;
+        }
+
+        public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, IFileSystem pfs, int programIndex)
+        {
+            Nca mainNca = null;
+            Nca patchNca = null;
+            Nca controlNca = null;
+
+            fileSystem.ImportTickets(pfs);
+
+            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
+            {
+                using var ncaFile = new UniqueRef<IFile>();
+
+                pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
+
+                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
+
+                if (ncaProgramIndex != programIndex)
+                {
+                    continue;
+                }
+
+                if (nca.Header.ContentType == NcaContentType.Program)
+                {
+                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
+
+                    if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
+                    {
+                        patchNca = nca;
+                    }
+                    else
+                    {
+                        mainNca = nca;
+                    }
+                }
+                else if (nca.Header.ContentType == NcaContentType.Control)
+                {
+                    controlNca = nca;
+                }
+            }
+
+            return (mainNca, patchNca, controlNca);
+        }
+
+        public static (Nca patch, Nca control) GetGameUpdateDataFromPartition(VirtualFileSystem fileSystem, PartitionFileSystem pfs, string titleId, int programIndex)
+        {
+            Nca patchNca = null;
+            Nca controlNca = null;
+
+            fileSystem.ImportTickets(pfs);
+
+            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
+            {
+                using var ncaFile = new UniqueRef<IFile>();
+
+                pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
+
+                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
+
+                if (ncaProgramIndex != programIndex)
+                {
+                    continue;
+                }
+
+                if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
+                {
+                    break;
+                }
+
+                if (nca.Header.ContentType == NcaContentType.Program)
+                {
+                    patchNca = nca;
+                }
+                else if (nca.Header.ContentType == NcaContentType.Control)
+                {
+                    controlNca = nca;
+                }
+            }
+
+            return (patchNca, controlNca);
+        }
+
+        public static (Nca patch, Nca control) GetGameUpdateData(VirtualFileSystem fileSystem, string titleId, int programIndex, out string updatePath)
+        {
+            updatePath = null;
+
+            if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdBase))
+            {
+                // Clear the program index part.
+                titleIdBase &= ~0xFUL;
+
+                // Load update information if exists.
+                string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json");
+
+                if (File.Exists(titleUpdateMetadataPath))
+                {
+                    updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
+
+                    if (File.Exists(updatePath))
+                    {
+                        FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
+                        PartitionFileSystem nsp = new();
+                        nsp.Initialize(file.AsStorage()).ThrowIfFailure();
+
+                        return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
+                    }
+                }
+            }
+
+            return (null, null);
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs b/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs
new file mode 100644
index 00000000..81193c5b
--- /dev/null
+++ b/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.App.Common
+{
+    public class ApplicationMetadata
+    {
+        public string Title { get; set; }
+        public bool Favorite { get; set; }
+
+        [JsonPropertyName("timespan_played")]
+        public TimeSpan TimePlayed { get; set; } = TimeSpan.Zero;
+
+        [JsonPropertyName("last_played_utc")]
+        public DateTime? LastPlayed { get; set; } = null;
+
+        [JsonPropertyName("time_played")]
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
+        public double TimePlayedOld { get; set; }
+
+        [JsonPropertyName("last_played")]
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
+        public string LastPlayedOld { get; set; }
+
+        /// <summary>
+        /// Updates <see cref="LastPlayed"/>. Call this before launching a game.
+        /// </summary>
+        public void UpdatePreGame()
+        {
+            LastPlayed = DateTime.UtcNow;
+        }
+
+        /// <summary>
+        /// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends.
+        /// </summary>
+        public void UpdatePostGame()
+        {
+            DateTime? prevLastPlayed = LastPlayed;
+            UpdatePreGame();
+
+            if (!prevLastPlayed.HasValue)
+            {
+                return;
+            }
+
+            TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value;
+            double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds;
+            TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero));
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs b/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs
new file mode 100644
index 00000000..a952e7ac
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs
@@ -0,0 +1,14 @@
+using Ryujinx.Common.Utilities;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    [JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))]
+    public enum AudioBackend
+    {
+        Dummy,
+        OpenAl,
+        SoundIo,
+        SDL2,
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
new file mode 100644
index 00000000..0ee51d83
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
@@ -0,0 +1,409 @@
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Multiplayer;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.UI.Common.Configuration.System;
+using Ryujinx.UI.Common.Configuration.UI;
+using System.Collections.Generic;
+using System.Text.Json.Nodes;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    public class ConfigurationFileFormat
+    {
+        /// <summary>
+        /// The current version of the file format
+        /// </summary>
+        public const int CurrentVersion = 48;
+
+        /// <summary>
+        /// Version of the configuration file format
+        /// </summary>
+        public int Version { get; set; }
+
+        /// <summary>
+        /// Enables or disables logging to a file on disk
+        /// </summary>
+        public bool EnableFileLog { get; set; }
+
+        /// <summary>
+        /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime.
+        /// </summary>
+        public BackendThreading BackendThreading { get; set; }
+
+        /// <summary>
+        /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead.
+        /// </summary>
+        public int ResScale { get; set; }
+
+        /// <summary>
+        /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.
+        /// </summary>
+        public float ResScaleCustom { get; set; }
+
+        /// <summary>
+        /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide.
+        /// </summary>
+        public float MaxAnisotropy { get; set; }
+
+        /// <summary>
+        /// Aspect Ratio applied to the renderer window.
+        /// </summary>
+        public AspectRatio AspectRatio { get; set; }
+
+        /// <summary>
+        /// Applies anti-aliasing to the renderer.
+        /// </summary>
+        public AntiAliasing AntiAliasing { get; set; }
+
+        /// <summary>
+        /// Sets the framebuffer upscaling type.
+        /// </summary>
+        public ScalingFilter ScalingFilter { get; set; }
+
+        /// <summary>
+        /// Sets the framebuffer upscaling level.
+        /// </summary>
+        public int ScalingFilterLevel { get; set; }
+
+        /// <summary>
+        /// Dumps shaders in this local directory
+        /// </summary>
+        public string GraphicsShadersDumpPath { get; set; }
+
+        /// <summary>
+        /// Enables printing debug log messages
+        /// </summary>
+        public bool LoggingEnableDebug { get; set; }
+
+        /// <summary>
+        /// Enables printing stub log messages
+        /// </summary>
+        public bool LoggingEnableStub { get; set; }
+
+        /// <summary>
+        /// Enables printing info log messages
+        /// </summary>
+        public bool LoggingEnableInfo { get; set; }
+
+        /// <summary>
+        /// Enables printing warning log messages
+        /// </summary>
+        public bool LoggingEnableWarn { get; set; }
+
+        /// <summary>
+        /// Enables printing error log messages
+        /// </summary>
+        public bool LoggingEnableError { get; set; }
+
+        /// <summary>
+        /// Enables printing trace log messages
+        /// </summary>
+        public bool LoggingEnableTrace { get; set; }
+
+        /// <summary>
+        /// Enables printing guest log messages
+        /// </summary>
+        public bool LoggingEnableGuest { get; set; }
+
+        /// <summary>
+        /// Enables printing FS access log messages
+        /// </summary>
+        public bool LoggingEnableFsAccessLog { get; set; }
+
+        /// <summary>
+        /// Controls which log messages are written to the log targets
+        /// </summary>
+        public LogClass[] LoggingFilteredClasses { get; set; }
+
+        /// <summary>
+        /// Change Graphics API debug log level
+        /// </summary>
+        public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; }
+
+        /// <summary>
+        /// Change System Language
+        /// </summary>
+        public Language SystemLanguage { get; set; }
+
+        /// <summary>
+        /// Change System Region
+        /// </summary>
+        public Region SystemRegion { get; set; }
+
+        /// <summary>
+        /// Change System TimeZone
+        /// </summary>
+        public string SystemTimeZone { get; set; }
+
+        /// <summary>
+        /// Change System Time Offset in seconds
+        /// </summary>
+        public long SystemTimeOffset { get; set; }
+
+        /// <summary>
+        /// Enables or disables Docked Mode
+        /// </summary>
+        public bool DockedMode { get; set; }
+
+        /// <summary>
+        /// Enables or disables Discord Rich Presence
+        /// </summary>
+        public bool EnableDiscordIntegration { get; set; }
+
+        /// <summary>
+        /// Checks for updates when Ryujinx starts when enabled
+        /// </summary>
+        public bool CheckUpdatesOnStart { get; set; }
+
+        /// <summary>
+        /// Show "Confirm Exit" Dialog
+        /// </summary>
+        public bool ShowConfirmExit { get; set; }
+
+        /// <summary>
+        /// Whether to hide cursor on idle, always or never
+        /// </summary>
+        public HideCursorMode HideCursor { get; set; }
+
+        /// <summary>
+        /// Enables or disables Vertical Sync
+        /// </summary>
+        public bool EnableVsync { get; set; }
+
+        /// <summary>
+        /// Enables or disables Shader cache
+        /// </summary>
+        public bool EnableShaderCache { get; set; }
+
+        /// <summary>
+        /// Enables or disables texture recompression
+        /// </summary>
+        public bool EnableTextureRecompression { get; set; }
+
+        /// <summary>
+        /// Enables or disables Macro high-level emulation
+        /// </summary>
+        public bool EnableMacroHLE { get; set; }
+
+        /// <summary>
+        /// Enables or disables color space passthrough, if available.
+        /// </summary>
+        public bool EnableColorSpacePassthrough { get; set; }
+
+        /// <summary>
+        /// Enables or disables profiled translation cache persistency
+        /// </summary>
+        public bool EnablePtc { get; set; }
+
+        /// <summary>
+        /// Enables or disables guest Internet access
+        /// </summary>
+        public bool EnableInternetAccess { get; set; }
+
+        /// <summary>
+        /// Enables integrity checks on Game content files
+        /// </summary>
+        public bool EnableFsIntegrityChecks { get; set; }
+
+        /// <summary>
+        /// Enables FS access log output to the console. Possible modes are 0-3
+        /// </summary>
+        public int FsGlobalAccessLogMode { get; set; }
+
+        /// <summary>
+        /// The selected audio backend
+        /// </summary>
+        public AudioBackend AudioBackend { get; set; }
+
+        /// <summary>
+        /// The audio volume
+        /// </summary>
+        public float AudioVolume { get; set; }
+
+        /// <summary>
+        /// The selected memory manager mode
+        /// </summary>
+        public MemoryManagerMode MemoryManagerMode { get; set; }
+
+        /// <summary>
+        /// Expands the RAM amount on the emulated system from 4GiB to 6GiB
+        /// </summary>
+        public bool ExpandRam { get; set; }
+
+        /// <summary>
+        /// Enable or disable ignoring missing services
+        /// </summary>
+        public bool IgnoreMissingServices { get; set; }
+
+        /// <summary>
+        /// Used to toggle columns in the GUI
+        /// </summary>
+        public GuiColumns GuiColumns { get; set; }
+
+        /// <summary>
+        /// Used to configure column sort settings in the GUI
+        /// </summary>
+        public ColumnSort ColumnSort { get; set; }
+
+        /// <summary>
+        /// A list of directories containing games to be used to load games into the games list
+        /// </summary>
+        public List<string> GameDirs { get; set; }
+
+        /// <summary>
+        /// A list of file types to be hidden in the games List
+        /// </summary>
+        public ShownFileTypes ShownFileTypes { get; set; }
+
+        /// <summary>
+        /// Main window start-up position, size and state
+        /// </summary>
+        public WindowStartup WindowStartup { get; set; }
+
+        /// <summary>
+        /// Language Code for the UI
+        /// </summary>
+        public string LanguageCode { get; set; }
+
+        /// <summary>
+        /// Enable or disable custom themes in the GUI
+        /// </summary>
+        public bool EnableCustomTheme { get; set; }
+
+        /// <summary>
+        /// Path to custom GUI theme
+        /// </summary>
+        public string CustomThemePath { get; set; }
+
+        /// <summary>
+        /// Chooses the base style // Not Used
+        /// </summary>
+        public string BaseStyle { get; set; }
+
+        /// <summary>
+        /// Chooses the view mode of the game list // Not Used
+        /// </summary>
+        public int GameListViewMode { get; set; }
+
+        /// <summary>
+        /// Show application name in Grid Mode // Not Used
+        /// </summary>
+        public bool ShowNames { get; set; }
+
+        /// <summary>
+        /// Sets App Icon Size // Not Used
+        /// </summary>
+        public int GridSize { get; set; }
+
+        /// <summary>
+        /// Sorts Apps in the game list // Not Used
+        /// </summary>
+        public int ApplicationSort { get; set; }
+
+        /// <summary>
+        /// Sets if Grid is ordered in Ascending Order // Not Used
+        /// </summary>
+        public bool IsAscendingOrder { get; set; }
+
+        /// <summary>
+        /// Start games in fullscreen mode
+        /// </summary>
+        public bool StartFullscreen { get; set; }
+
+        /// <summary>
+        /// Show console window
+        /// </summary>
+        public bool ShowConsole { get; set; }
+
+        /// <summary>
+        /// Enable or disable keyboard support (Independent from controllers binding)
+        /// </summary>
+        public bool EnableKeyboard { get; set; }
+
+        /// <summary>
+        /// Enable or disable mouse support (Independent from controllers binding)
+        /// </summary>
+        public bool EnableMouse { get; set; }
+
+        /// <summary>
+        /// Hotkey Keyboard Bindings
+        /// </summary>
+        public KeyboardHotkeys Hotkeys { get; set; }
+
+        /// <summary>
+        /// Legacy keyboard control bindings
+        /// </summary>
+        /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
+        /// TODO: Remove this when those older versions aren't in use anymore.
+        public List<JsonObject> KeyboardConfig { get; set; }
+
+        /// <summary>
+        /// Legacy controller control bindings
+        /// </summary>
+        /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
+        /// TODO: Remove this when those older versions aren't in use anymore.
+        public List<JsonObject> ControllerConfig { get; set; }
+
+        /// <summary>
+        /// Input configurations
+        /// </summary>
+        public List<InputConfig> InputConfig { get; set; }
+
+        /// <summary>
+        /// Graphics backend
+        /// </summary>
+        public GraphicsBackend GraphicsBackend { get; set; }
+
+        /// <summary>
+        /// Preferred GPU
+        /// </summary>
+        public string PreferredGpu { get; set; }
+
+        /// <summary>
+        /// Multiplayer Mode
+        /// </summary>
+        public MultiplayerMode MultiplayerMode { get; set; }
+
+        /// <summary>
+        /// GUID for the network interface used by LAN (or 0 for default)
+        /// </summary>
+        public string MultiplayerLanInterfaceId { get; set; }
+
+        /// <summary>
+        /// Uses Hypervisor over JIT if available
+        /// </summary>
+        public bool UseHypervisor { get; set; }
+
+        /// <summary>
+        /// Loads a configuration file from disk
+        /// </summary>
+        /// <param name="path">The path to the JSON configuration file</param>
+        /// <param name="configurationFileFormat">Parsed configuration file</param>
+        public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat)
+        {
+            try
+            {
+                configurationFileFormat = JsonHelper.DeserializeFromFile(path, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat);
+
+                return configurationFileFormat.Version != 0;
+            }
+            catch
+            {
+                configurationFileFormat = null;
+
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Save a configuration file to disk
+        /// </summary>
+        /// <param name="path">The path to the JSON configuration file</param>
+        public void SaveConfig(string path)
+        {
+            JsonHelper.SerializeToFile(path, this, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat);
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs
new file mode 100644
index 00000000..9861ebf1
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs
@@ -0,0 +1,9 @@
+using Ryujinx.Common.Utilities;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    internal static class ConfigurationFileFormatSettings
+    {
+        public static readonly ConfigurationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs
new file mode 100644
index 00000000..3c3e3f20
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    [JsonSourceGenerationOptions(WriteIndented = true)]
+    [JsonSerializable(typeof(ConfigurationFileFormat))]
+    internal partial class ConfigurationJsonSerializerContext : JsonSerializerContext
+    {
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
new file mode 100644
index 00000000..1d6934ce
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
@@ -0,0 +1,1562 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Hid.Controller;
+using Ryujinx.Common.Configuration.Hid.Keyboard;
+using Ryujinx.Common.Configuration.Multiplayer;
+using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Vulkan;
+using Ryujinx.UI.Common.Configuration.System;
+using Ryujinx.UI.Common.Configuration.UI;
+using Ryujinx.UI.Common.Helper;
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Nodes;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    public class ConfigurationState
+    {
+        /// <summary>
+        /// UI configuration section
+        /// </summary>
+        public class UISection
+        {
+            public class Columns
+            {
+                public ReactiveObject<bool> FavColumn { get; private set; }
+                public ReactiveObject<bool> IconColumn { get; private set; }
+                public ReactiveObject<bool> AppColumn { get; private set; }
+                public ReactiveObject<bool> DevColumn { get; private set; }
+                public ReactiveObject<bool> VersionColumn { get; private set; }
+                public ReactiveObject<bool> TimePlayedColumn { get; private set; }
+                public ReactiveObject<bool> LastPlayedColumn { get; private set; }
+                public ReactiveObject<bool> FileExtColumn { get; private set; }
+                public ReactiveObject<bool> FileSizeColumn { get; private set; }
+                public ReactiveObject<bool> PathColumn { get; private set; }
+
+                public Columns()
+                {
+                    FavColumn = new ReactiveObject<bool>();
+                    IconColumn = new ReactiveObject<bool>();
+                    AppColumn = new ReactiveObject<bool>();
+                    DevColumn = new ReactiveObject<bool>();
+                    VersionColumn = new ReactiveObject<bool>();
+                    TimePlayedColumn = new ReactiveObject<bool>();
+                    LastPlayedColumn = new ReactiveObject<bool>();
+                    FileExtColumn = new ReactiveObject<bool>();
+                    FileSizeColumn = new ReactiveObject<bool>();
+                    PathColumn = new ReactiveObject<bool>();
+                }
+            }
+
+            public class ColumnSortSettings
+            {
+                public ReactiveObject<int> SortColumnId { get; private set; }
+                public ReactiveObject<bool> SortAscending { get; private set; }
+
+                public ColumnSortSettings()
+                {
+                    SortColumnId = new ReactiveObject<int>();
+                    SortAscending = new ReactiveObject<bool>();
+                }
+            }
+
+            /// <summary>
+            /// Used to toggle which file types are shown in the UI
+            /// </summary>
+            public class ShownFileTypeSettings
+            {
+                public ReactiveObject<bool> NSP { get; private set; }
+                public ReactiveObject<bool> PFS0 { get; private set; }
+                public ReactiveObject<bool> XCI { get; private set; }
+                public ReactiveObject<bool> NCA { get; private set; }
+                public ReactiveObject<bool> NRO { get; private set; }
+                public ReactiveObject<bool> NSO { get; private set; }
+
+                public ShownFileTypeSettings()
+                {
+                    NSP = new ReactiveObject<bool>();
+                    PFS0 = new ReactiveObject<bool>();
+                    XCI = new ReactiveObject<bool>();
+                    NCA = new ReactiveObject<bool>();
+                    NRO = new ReactiveObject<bool>();
+                    NSO = new ReactiveObject<bool>();
+                }
+            }
+
+            // <summary>
+            /// Determines main window start-up position, size and state
+            ///<summary>
+            public class WindowStartupSettings
+            {
+                public ReactiveObject<int> WindowSizeWidth { get; private set; }
+                public ReactiveObject<int> WindowSizeHeight { get; private set; }
+                public ReactiveObject<int> WindowPositionX { get; private set; }
+                public ReactiveObject<int> WindowPositionY { get; private set; }
+                public ReactiveObject<bool> WindowMaximized { get; private set; }
+
+                public WindowStartupSettings()
+                {
+                    WindowSizeWidth = new ReactiveObject<int>();
+                    WindowSizeHeight = new ReactiveObject<int>();
+                    WindowPositionX = new ReactiveObject<int>();
+                    WindowPositionY = new ReactiveObject<int>();
+                    WindowMaximized = new ReactiveObject<bool>();
+                }
+            }
+
+            /// <summary>
+            /// Used to toggle columns in the GUI
+            /// </summary>
+            public Columns GuiColumns { get; private set; }
+
+            /// <summary>
+            /// Used to configure column sort settings in the GUI
+            /// </summary>
+            public ColumnSortSettings ColumnSort { get; private set; }
+
+            /// <summary>
+            /// A list of directories containing games to be used to load games into the games list
+            /// </summary>
+            public ReactiveObject<List<string>> GameDirs { get; private set; }
+
+            /// <summary>
+            /// A list of file types to be hidden in the games List
+            /// </summary>
+            public ShownFileTypeSettings ShownFileTypes { get; private set; }
+
+            /// <summary>
+            /// Determines main window start-up position, size and state
+            /// </summary>
+            public WindowStartupSettings WindowStartup { get; private set; }
+
+            /// <summary>
+            /// Language Code for the UI
+            /// </summary>
+            public ReactiveObject<string> LanguageCode { get; private set; }
+
+            /// <summary>
+            /// Enable or disable custom themes in the GUI
+            /// </summary>
+            public ReactiveObject<bool> EnableCustomTheme { get; private set; }
+
+            /// <summary>
+            /// Path to custom GUI theme
+            /// </summary>
+            public ReactiveObject<string> CustomThemePath { get; private set; }
+
+            /// <summary>
+            /// Selects the base style
+            /// </summary>
+            public ReactiveObject<string> BaseStyle { get; private set; }
+
+            /// <summary>
+            /// Start games in fullscreen mode
+            /// </summary>
+            public ReactiveObject<bool> StartFullscreen { get; private set; }
+
+            /// <summary>
+            /// Hide / Show Console Window
+            /// </summary>
+            public ReactiveObject<bool> ShowConsole { get; private set; }
+
+            /// <summary>
+            /// View Mode of the Game list
+            /// </summary>
+            public ReactiveObject<int> GameListViewMode { get; private set; }
+
+            /// <summary>
+            /// Show application name in Grid Mode
+            /// </summary>
+            public ReactiveObject<bool> ShowNames { get; private set; }
+
+            /// <summary>
+            /// Sets App Icon Size in Grid Mode
+            /// </summary>
+            public ReactiveObject<int> GridSize { get; private set; }
+
+            /// <summary>
+            /// Sorts Apps in Grid Mode
+            /// </summary>
+            public ReactiveObject<int> ApplicationSort { get; private set; }
+
+            /// <summary>
+            /// Sets if Grid is ordered in Ascending Order
+            /// </summary>
+            public ReactiveObject<bool> IsAscendingOrder { get; private set; }
+
+            public UISection()
+            {
+                GuiColumns = new Columns();
+                ColumnSort = new ColumnSortSettings();
+                GameDirs = new ReactiveObject<List<string>>();
+                ShownFileTypes = new ShownFileTypeSettings();
+                WindowStartup = new WindowStartupSettings();
+                EnableCustomTheme = new ReactiveObject<bool>();
+                CustomThemePath = new ReactiveObject<string>();
+                BaseStyle = new ReactiveObject<string>();
+                StartFullscreen = new ReactiveObject<bool>();
+                GameListViewMode = new ReactiveObject<int>();
+                ShowNames = new ReactiveObject<bool>();
+                GridSize = new ReactiveObject<int>();
+                ApplicationSort = new ReactiveObject<int>();
+                IsAscendingOrder = new ReactiveObject<bool>();
+                LanguageCode = new ReactiveObject<string>();
+                ShowConsole = new ReactiveObject<bool>();
+                ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
+            }
+        }
+
+        /// <summary>
+        /// Logger configuration section
+        /// </summary>
+        public class LoggerSection
+        {
+            /// <summary>
+            /// Enables printing debug log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableDebug { get; private set; }
+
+            /// <summary>
+            /// Enables printing stub log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableStub { get; private set; }
+
+            /// <summary>
+            /// Enables printing info log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableInfo { get; private set; }
+
+            /// <summary>
+            /// Enables printing warning log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableWarn { get; private set; }
+
+            /// <summary>
+            /// Enables printing error log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableError { get; private set; }
+
+            /// <summary>
+            /// Enables printing trace log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableTrace { get; private set; }
+
+            /// <summary>
+            /// Enables printing guest log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableGuest { get; private set; }
+
+            /// <summary>
+            /// Enables printing FS access log messages
+            /// </summary>
+            public ReactiveObject<bool> EnableFsAccessLog { get; private set; }
+
+            /// <summary>
+            /// Controls which log messages are written to the log targets
+            /// </summary>
+            public ReactiveObject<LogClass[]> FilteredClasses { get; private set; }
+
+            /// <summary>
+            /// Enables or disables logging to a file on disk
+            /// </summary>
+            public ReactiveObject<bool> EnableFileLog { get; private set; }
+
+            /// <summary>
+            /// Controls which OpenGL log messages are recorded in the log
+            /// </summary>
+            public ReactiveObject<GraphicsDebugLevel> GraphicsDebugLevel { get; private set; }
+
+            public LoggerSection()
+            {
+                EnableDebug = new ReactiveObject<bool>();
+                EnableStub = new ReactiveObject<bool>();
+                EnableInfo = new ReactiveObject<bool>();
+                EnableWarn = new ReactiveObject<bool>();
+                EnableError = new ReactiveObject<bool>();
+                EnableTrace = new ReactiveObject<bool>();
+                EnableGuest = new ReactiveObject<bool>();
+                EnableFsAccessLog = new ReactiveObject<bool>();
+                FilteredClasses = new ReactiveObject<LogClass[]>();
+                EnableFileLog = new ReactiveObject<bool>();
+                EnableFileLog.Event += static (sender, e) => LogValueChange(e, nameof(EnableFileLog));
+                GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
+            }
+        }
+
+        /// <summary>
+        /// System configuration section
+        /// </summary>
+        public class SystemSection
+        {
+            /// <summary>
+            /// Change System Language
+            /// </summary>
+            public ReactiveObject<Language> Language { get; private set; }
+
+            /// <summary>
+            /// Change System Region
+            /// </summary>
+            public ReactiveObject<Region> Region { get; private set; }
+
+            /// <summary>
+            /// Change System TimeZone
+            /// </summary>
+            public ReactiveObject<string> TimeZone { get; private set; }
+
+            /// <summary>
+            /// System Time Offset in Seconds
+            /// </summary>
+            public ReactiveObject<long> SystemTimeOffset { get; private set; }
+
+            /// <summary>
+            /// Enables or disables Docked Mode
+            /// </summary>
+            public ReactiveObject<bool> EnableDockedMode { get; private set; }
+
+            /// <summary>
+            /// Enables or disables profiled translation cache persistency
+            /// </summary>
+            public ReactiveObject<bool> EnablePtc { get; private set; }
+
+            /// <summary>
+            /// Enables or disables guest Internet access
+            /// </summary>
+            public ReactiveObject<bool> EnableInternetAccess { get; private set; }
+
+            /// <summary>
+            /// Enables integrity checks on Game content files
+            /// </summary>
+            public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
+
+            /// <summary>
+            /// Enables FS access log output to the console. Possible modes are 0-3
+            /// </summary>
+            public ReactiveObject<int> FsGlobalAccessLogMode { get; private set; }
+
+            /// <summary>
+            /// The selected audio backend
+            /// </summary>
+            public ReactiveObject<AudioBackend> AudioBackend { get; private set; }
+
+            /// <summary>
+            /// The audio backend volume
+            /// </summary>
+            public ReactiveObject<float> AudioVolume { get; private set; }
+
+            /// <summary>
+            /// The selected memory manager mode
+            /// </summary>
+            public ReactiveObject<MemoryManagerMode> MemoryManagerMode { get; private set; }
+
+            /// <summary>
+            /// Defines the amount of RAM available on the emulated system, and how it is distributed
+            /// </summary>
+            public ReactiveObject<bool> ExpandRam { get; private set; }
+
+            /// <summary>
+            /// Enable or disable ignoring missing services
+            /// </summary>
+            public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
+
+            /// <summary>
+            /// Uses Hypervisor over JIT if available
+            /// </summary>
+            public ReactiveObject<bool> UseHypervisor { get; private set; }
+
+            public SystemSection()
+            {
+                Language = new ReactiveObject<Language>();
+                Region = new ReactiveObject<Region>();
+                TimeZone = new ReactiveObject<string>();
+                SystemTimeOffset = new ReactiveObject<long>();
+                EnableDockedMode = new ReactiveObject<bool>();
+                EnableDockedMode.Event += static (sender, e) => LogValueChange(e, nameof(EnableDockedMode));
+                EnablePtc = new ReactiveObject<bool>();
+                EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
+                EnableInternetAccess = new ReactiveObject<bool>();
+                EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess));
+                EnableFsIntegrityChecks = new ReactiveObject<bool>();
+                EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks));
+                FsGlobalAccessLogMode = new ReactiveObject<int>();
+                FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(e, nameof(FsGlobalAccessLogMode));
+                AudioBackend = new ReactiveObject<AudioBackend>();
+                AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend));
+                MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
+                MemoryManagerMode.Event += static (sender, e) => LogValueChange(e, nameof(MemoryManagerMode));
+                ExpandRam = new ReactiveObject<bool>();
+                ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam));
+                IgnoreMissingServices = new ReactiveObject<bool>();
+                IgnoreMissingServices.Event += static (sender, e) => LogValueChange(e, nameof(IgnoreMissingServices));
+                AudioVolume = new ReactiveObject<float>();
+                AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume));
+                UseHypervisor = new ReactiveObject<bool>();
+                UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor));
+            }
+        }
+
+        /// <summary>
+        /// Hid configuration section
+        /// </summary>
+        public class HidSection
+        {
+            /// <summary>
+            /// Enable or disable keyboard support (Independent from controllers binding)
+            /// </summary>
+            public ReactiveObject<bool> EnableKeyboard { get; private set; }
+
+            /// <summary>
+            /// Enable or disable mouse support (Independent from controllers binding)
+            /// </summary>
+            public ReactiveObject<bool> EnableMouse { get; private set; }
+
+            /// <summary>
+            /// Hotkey Keyboard Bindings
+            /// </summary>
+            public ReactiveObject<KeyboardHotkeys> Hotkeys { get; private set; }
+
+            /// <summary>
+            /// Input device configuration.
+            /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed.
+            /// TODO: Implement a ReactiveList class.
+            /// </summary>
+            public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
+
+            public HidSection()
+            {
+                EnableKeyboard = new ReactiveObject<bool>();
+                EnableMouse = new ReactiveObject<bool>();
+                Hotkeys = new ReactiveObject<KeyboardHotkeys>();
+                InputConfig = new ReactiveObject<List<InputConfig>>();
+            }
+        }
+
+        /// <summary>
+        /// Graphics configuration section
+        /// </summary>
+        public class GraphicsSection
+        {
+            /// <summary>
+            /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime.
+            /// </summary>
+            public ReactiveObject<BackendThreading> BackendThreading { get; private set; }
+
+            /// <summary>
+            /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide.
+            /// </summary>
+            public ReactiveObject<float> MaxAnisotropy { get; private set; }
+
+            /// <summary>
+            /// Aspect Ratio applied to the renderer window.
+            /// </summary>
+            public ReactiveObject<AspectRatio> AspectRatio { get; private set; }
+
+            /// <summary>
+            /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead.
+            /// </summary>
+            public ReactiveObject<int> ResScale { get; private set; }
+
+            /// <summary>
+            /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.
+            /// </summary>
+            public ReactiveObject<float> ResScaleCustom { get; private set; }
+
+            /// <summary>
+            /// Dumps shaders in this local directory
+            /// </summary>
+            public ReactiveObject<string> ShadersDumpPath { get; private set; }
+
+            /// <summary>
+            /// Enables or disables Vertical Sync
+            /// </summary>
+            public ReactiveObject<bool> EnableVsync { get; private set; }
+
+            /// <summary>
+            /// Enables or disables Shader cache
+            /// </summary>
+            public ReactiveObject<bool> EnableShaderCache { get; private set; }
+
+            /// <summary>
+            /// Enables or disables texture recompression
+            /// </summary>
+            public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
+
+            /// <summary>
+            /// Enables or disables Macro high-level emulation
+            /// </summary>
+            public ReactiveObject<bool> EnableMacroHLE { get; private set; }
+
+            /// <summary>
+            /// Enables or disables color space passthrough, if available.
+            /// </summary>
+            public ReactiveObject<bool> EnableColorSpacePassthrough { get; private set; }
+
+            /// <summary>
+            /// Graphics backend
+            /// </summary>
+            public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; }
+
+            /// <summary>
+            /// Applies anti-aliasing to the renderer.
+            /// </summary>
+            public ReactiveObject<AntiAliasing> AntiAliasing { get; private set; }
+
+            /// <summary>
+            /// Sets the framebuffer upscaling type.
+            /// </summary>
+            public ReactiveObject<ScalingFilter> ScalingFilter { get; private set; }
+
+            /// <summary>
+            /// Sets the framebuffer upscaling level.
+            /// </summary>
+            public ReactiveObject<int> ScalingFilterLevel { get; private set; }
+
+            /// <summary>
+            /// Preferred GPU
+            /// </summary>
+            public ReactiveObject<string> PreferredGpu { get; private set; }
+
+            public GraphicsSection()
+            {
+                BackendThreading = new ReactiveObject<BackendThreading>();
+                BackendThreading.Event += static (sender, e) => LogValueChange(e, nameof(BackendThreading));
+                ResScale = new ReactiveObject<int>();
+                ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale));
+                ResScaleCustom = new ReactiveObject<float>();
+                ResScaleCustom.Event += static (sender, e) => LogValueChange(e, nameof(ResScaleCustom));
+                MaxAnisotropy = new ReactiveObject<float>();
+                MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy));
+                AspectRatio = new ReactiveObject<AspectRatio>();
+                AspectRatio.Event += static (sender, e) => LogValueChange(e, nameof(AspectRatio));
+                ShadersDumpPath = new ReactiveObject<string>();
+                EnableVsync = new ReactiveObject<bool>();
+                EnableVsync.Event += static (sender, e) => LogValueChange(e, nameof(EnableVsync));
+                EnableShaderCache = new ReactiveObject<bool>();
+                EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache));
+                EnableTextureRecompression = new ReactiveObject<bool>();
+                EnableTextureRecompression.Event += static (sender, e) => LogValueChange(e, nameof(EnableTextureRecompression));
+                GraphicsBackend = new ReactiveObject<GraphicsBackend>();
+                GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend));
+                PreferredGpu = new ReactiveObject<string>();
+                PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu));
+                EnableMacroHLE = new ReactiveObject<bool>();
+                EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
+                EnableColorSpacePassthrough = new ReactiveObject<bool>();
+                EnableColorSpacePassthrough.Event += static (sender, e) => LogValueChange(e, nameof(EnableColorSpacePassthrough));
+                AntiAliasing = new ReactiveObject<AntiAliasing>();
+                AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing));
+                ScalingFilter = new ReactiveObject<ScalingFilter>();
+                ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter));
+                ScalingFilterLevel = new ReactiveObject<int>();
+                ScalingFilterLevel.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilterLevel));
+            }
+        }
+
+        /// <summary>
+        /// Multiplayer configuration section
+        /// </summary>
+        public class MultiplayerSection
+        {
+            /// <summary>
+            /// GUID for the network interface used by LAN (or 0 for default)
+            /// </summary>
+            public ReactiveObject<string> LanInterfaceId { get; private set; }
+
+            /// <summary>
+            /// Multiplayer Mode
+            /// </summary>
+            public ReactiveObject<MultiplayerMode> Mode { get; private set; }
+
+            public MultiplayerSection()
+            {
+                LanInterfaceId = new ReactiveObject<string>();
+                Mode = new ReactiveObject<MultiplayerMode>();
+                Mode.Event += static (_, e) => LogValueChange(e, nameof(MultiplayerMode));
+            }
+        }
+
+        /// <summary>
+        /// The default configuration instance
+        /// </summary>
+        public static ConfigurationState Instance { get; private set; }
+
+        /// <summary>
+        /// The UI section
+        /// </summary>
+        public UISection UI { get; private set; }
+
+        /// <summary>
+        /// The Logger section
+        /// </summary>
+        public LoggerSection Logger { get; private set; }
+
+        /// <summary>
+        /// The System section
+        /// </summary>
+        public SystemSection System { get; private set; }
+
+        /// <summary>
+        /// The Graphics section
+        /// </summary>
+        public GraphicsSection Graphics { get; private set; }
+
+        /// <summary>
+        /// The Hid section
+        /// </summary>
+        public HidSection Hid { get; private set; }
+
+        /// <summary>
+        /// The Multiplayer section
+        /// </summary>
+        public MultiplayerSection Multiplayer { get; private set; }
+
+        /// <summary>
+        /// Enables or disables Discord Rich Presence
+        /// </summary>
+        public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
+
+        /// <summary>
+        /// Checks for updates when Ryujinx starts when enabled
+        /// </summary>
+        public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
+
+        /// <summary>
+        /// Show "Confirm Exit" Dialog
+        /// </summary>
+        public ReactiveObject<bool> ShowConfirmExit { get; private set; }
+
+        /// <summary>
+        /// Hide Cursor on Idle
+        /// </summary>
+        public ReactiveObject<HideCursorMode> HideCursor { get; private set; }
+
+        private ConfigurationState()
+        {
+            UI = new UISection();
+            Logger = new LoggerSection();
+            System = new SystemSection();
+            Graphics = new GraphicsSection();
+            Hid = new HidSection();
+            Multiplayer = new MultiplayerSection();
+            EnableDiscordIntegration = new ReactiveObject<bool>();
+            CheckUpdatesOnStart = new ReactiveObject<bool>();
+            ShowConfirmExit = new ReactiveObject<bool>();
+            HideCursor = new ReactiveObject<HideCursorMode>();
+        }
+
+        public ConfigurationFileFormat ToFileFormat()
+        {
+            ConfigurationFileFormat configurationFile = new()
+            {
+                Version = ConfigurationFileFormat.CurrentVersion,
+                BackendThreading = Graphics.BackendThreading,
+                EnableFileLog = Logger.EnableFileLog,
+                ResScale = Graphics.ResScale,
+                ResScaleCustom = Graphics.ResScaleCustom,
+                MaxAnisotropy = Graphics.MaxAnisotropy,
+                AspectRatio = Graphics.AspectRatio,
+                AntiAliasing = Graphics.AntiAliasing,
+                ScalingFilter = Graphics.ScalingFilter,
+                ScalingFilterLevel = Graphics.ScalingFilterLevel,
+                GraphicsShadersDumpPath = Graphics.ShadersDumpPath,
+                LoggingEnableDebug = Logger.EnableDebug,
+                LoggingEnableStub = Logger.EnableStub,
+                LoggingEnableInfo = Logger.EnableInfo,
+                LoggingEnableWarn = Logger.EnableWarn,
+                LoggingEnableError = Logger.EnableError,
+                LoggingEnableTrace = Logger.EnableTrace,
+                LoggingEnableGuest = Logger.EnableGuest,
+                LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
+                LoggingFilteredClasses = Logger.FilteredClasses,
+                LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel,
+                SystemLanguage = System.Language,
+                SystemRegion = System.Region,
+                SystemTimeZone = System.TimeZone,
+                SystemTimeOffset = System.SystemTimeOffset,
+                DockedMode = System.EnableDockedMode,
+                EnableDiscordIntegration = EnableDiscordIntegration,
+                CheckUpdatesOnStart = CheckUpdatesOnStart,
+                ShowConfirmExit = ShowConfirmExit,
+                HideCursor = HideCursor,
+                EnableVsync = Graphics.EnableVsync,
+                EnableShaderCache = Graphics.EnableShaderCache,
+                EnableTextureRecompression = Graphics.EnableTextureRecompression,
+                EnableMacroHLE = Graphics.EnableMacroHLE,
+                EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough,
+                EnablePtc = System.EnablePtc,
+                EnableInternetAccess = System.EnableInternetAccess,
+                EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
+                FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
+                AudioBackend = System.AudioBackend,
+                AudioVolume = System.AudioVolume,
+                MemoryManagerMode = System.MemoryManagerMode,
+                ExpandRam = System.ExpandRam,
+                IgnoreMissingServices = System.IgnoreMissingServices,
+                UseHypervisor = System.UseHypervisor,
+                GuiColumns = new GuiColumns
+                {
+                    FavColumn = UI.GuiColumns.FavColumn,
+                    IconColumn = UI.GuiColumns.IconColumn,
+                    AppColumn = UI.GuiColumns.AppColumn,
+                    DevColumn = UI.GuiColumns.DevColumn,
+                    VersionColumn = UI.GuiColumns.VersionColumn,
+                    TimePlayedColumn = UI.GuiColumns.TimePlayedColumn,
+                    LastPlayedColumn = UI.GuiColumns.LastPlayedColumn,
+                    FileExtColumn = UI.GuiColumns.FileExtColumn,
+                    FileSizeColumn = UI.GuiColumns.FileSizeColumn,
+                    PathColumn = UI.GuiColumns.PathColumn,
+                },
+                ColumnSort = new ColumnSort
+                {
+                    SortColumnId = UI.ColumnSort.SortColumnId,
+                    SortAscending = UI.ColumnSort.SortAscending,
+                },
+                GameDirs = UI.GameDirs,
+                ShownFileTypes = new ShownFileTypes
+                {
+                    NSP = UI.ShownFileTypes.NSP,
+                    PFS0 = UI.ShownFileTypes.PFS0,
+                    XCI = UI.ShownFileTypes.XCI,
+                    NCA = UI.ShownFileTypes.NCA,
+                    NRO = UI.ShownFileTypes.NRO,
+                    NSO = UI.ShownFileTypes.NSO,
+                },
+                WindowStartup = new WindowStartup
+                {
+                    WindowSizeWidth = UI.WindowStartup.WindowSizeWidth,
+                    WindowSizeHeight = UI.WindowStartup.WindowSizeHeight,
+                    WindowPositionX = UI.WindowStartup.WindowPositionX,
+                    WindowPositionY = UI.WindowStartup.WindowPositionY,
+                    WindowMaximized = UI.WindowStartup.WindowMaximized,
+                },
+                LanguageCode = UI.LanguageCode,
+                EnableCustomTheme = UI.EnableCustomTheme,
+                CustomThemePath = UI.CustomThemePath,
+                BaseStyle = UI.BaseStyle,
+                GameListViewMode = UI.GameListViewMode,
+                ShowNames = UI.ShowNames,
+                GridSize = UI.GridSize,
+                ApplicationSort = UI.ApplicationSort,
+                IsAscendingOrder = UI.IsAscendingOrder,
+                StartFullscreen = UI.StartFullscreen,
+                ShowConsole = UI.ShowConsole,
+                EnableKeyboard = Hid.EnableKeyboard,
+                EnableMouse = Hid.EnableMouse,
+                Hotkeys = Hid.Hotkeys,
+                KeyboardConfig = new List<JsonObject>(),
+                ControllerConfig = new List<JsonObject>(),
+                InputConfig = Hid.InputConfig,
+                GraphicsBackend = Graphics.GraphicsBackend,
+                PreferredGpu = Graphics.PreferredGpu,
+                MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
+                MultiplayerMode = Multiplayer.Mode,
+            };
+
+            return configurationFile;
+        }
+
+        public void LoadDefault()
+        {
+            Logger.EnableFileLog.Value = true;
+            Graphics.BackendThreading.Value = BackendThreading.Auto;
+            Graphics.ResScale.Value = 1;
+            Graphics.ResScaleCustom.Value = 1.0f;
+            Graphics.MaxAnisotropy.Value = -1.0f;
+            Graphics.AspectRatio.Value = AspectRatio.Fixed16x9;
+            Graphics.GraphicsBackend.Value = DefaultGraphicsBackend();
+            Graphics.PreferredGpu.Value = "";
+            Graphics.ShadersDumpPath.Value = "";
+            Logger.EnableDebug.Value = false;
+            Logger.EnableStub.Value = true;
+            Logger.EnableInfo.Value = true;
+            Logger.EnableWarn.Value = true;
+            Logger.EnableError.Value = true;
+            Logger.EnableTrace.Value = false;
+            Logger.EnableGuest.Value = true;
+            Logger.EnableFsAccessLog.Value = false;
+            Logger.FilteredClasses.Value = Array.Empty<LogClass>();
+            Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None;
+            System.Language.Value = Language.AmericanEnglish;
+            System.Region.Value = Region.USA;
+            System.TimeZone.Value = "UTC";
+            System.SystemTimeOffset.Value = 0;
+            System.EnableDockedMode.Value = true;
+            EnableDiscordIntegration.Value = true;
+            CheckUpdatesOnStart.Value = true;
+            ShowConfirmExit.Value = true;
+            HideCursor.Value = HideCursorMode.OnIdle;
+            Graphics.EnableVsync.Value = true;
+            Graphics.EnableShaderCache.Value = true;
+            Graphics.EnableTextureRecompression.Value = false;
+            Graphics.EnableMacroHLE.Value = true;
+            Graphics.EnableColorSpacePassthrough.Value = false;
+            Graphics.AntiAliasing.Value = AntiAliasing.None;
+            Graphics.ScalingFilter.Value = ScalingFilter.Bilinear;
+            Graphics.ScalingFilterLevel.Value = 80;
+            System.EnablePtc.Value = true;
+            System.EnableInternetAccess.Value = false;
+            System.EnableFsIntegrityChecks.Value = true;
+            System.FsGlobalAccessLogMode.Value = 0;
+            System.AudioBackend.Value = AudioBackend.SDL2;
+            System.AudioVolume.Value = 1;
+            System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
+            System.ExpandRam.Value = false;
+            System.IgnoreMissingServices.Value = false;
+            System.UseHypervisor.Value = true;
+            Multiplayer.LanInterfaceId.Value = "0";
+            Multiplayer.Mode.Value = MultiplayerMode.Disabled;
+            UI.GuiColumns.FavColumn.Value = true;
+            UI.GuiColumns.IconColumn.Value = true;
+            UI.GuiColumns.AppColumn.Value = true;
+            UI.GuiColumns.DevColumn.Value = true;
+            UI.GuiColumns.VersionColumn.Value = true;
+            UI.GuiColumns.TimePlayedColumn.Value = true;
+            UI.GuiColumns.LastPlayedColumn.Value = true;
+            UI.GuiColumns.FileExtColumn.Value = true;
+            UI.GuiColumns.FileSizeColumn.Value = true;
+            UI.GuiColumns.PathColumn.Value = true;
+            UI.ColumnSort.SortColumnId.Value = 0;
+            UI.ColumnSort.SortAscending.Value = false;
+            UI.GameDirs.Value = new List<string>();
+            UI.ShownFileTypes.NSP.Value = true;
+            UI.ShownFileTypes.PFS0.Value = true;
+            UI.ShownFileTypes.XCI.Value = true;
+            UI.ShownFileTypes.NCA.Value = true;
+            UI.ShownFileTypes.NRO.Value = true;
+            UI.ShownFileTypes.NSO.Value = true;
+            UI.EnableCustomTheme.Value = true;
+            UI.LanguageCode.Value = "en_US";
+            UI.CustomThemePath.Value = "";
+            UI.BaseStyle.Value = "Dark";
+            UI.GameListViewMode.Value = 0;
+            UI.ShowNames.Value = true;
+            UI.GridSize.Value = 2;
+            UI.ApplicationSort.Value = 0;
+            UI.IsAscendingOrder.Value = true;
+            UI.StartFullscreen.Value = false;
+            UI.ShowConsole.Value = true;
+            UI.WindowStartup.WindowSizeWidth.Value = 1280;
+            UI.WindowStartup.WindowSizeHeight.Value = 760;
+            UI.WindowStartup.WindowPositionX.Value = 0;
+            UI.WindowStartup.WindowPositionY.Value = 0;
+            UI.WindowStartup.WindowMaximized.Value = false;
+            Hid.EnableKeyboard.Value = false;
+            Hid.EnableMouse.Value = false;
+            Hid.Hotkeys.Value = new KeyboardHotkeys
+            {
+                ToggleVsync = Key.F1,
+                ToggleMute = Key.F2,
+                Screenshot = Key.F8,
+                ShowUI = Key.F4,
+                Pause = Key.F5,
+                ResScaleUp = Key.Unbound,
+                ResScaleDown = Key.Unbound,
+                VolumeUp = Key.Unbound,
+                VolumeDown = Key.Unbound,
+            };
+            Hid.InputConfig.Value = new List<InputConfig>
+            {
+                new StandardKeyboardInputConfig
+                {
+                    Version = InputConfig.CurrentVersion,
+                    Backend = InputBackendType.WindowKeyboard,
+                    Id = "0",
+                    PlayerIndex = PlayerIndex.Player1,
+                    ControllerType = ControllerType.JoyconPair,
+                    LeftJoycon = new LeftJoyconCommonConfig<Key>
+                    {
+                        DpadUp = Key.Up,
+                        DpadDown = Key.Down,
+                        DpadLeft = Key.Left,
+                        DpadRight = Key.Right,
+                        ButtonMinus = Key.Minus,
+                        ButtonL = Key.E,
+                        ButtonZl = Key.Q,
+                        ButtonSl = Key.Unbound,
+                        ButtonSr = Key.Unbound,
+                    },
+                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = Key.W,
+                        StickDown = Key.S,
+                        StickLeft = Key.A,
+                        StickRight = Key.D,
+                        StickButton = Key.F,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<Key>
+                    {
+                        ButtonA = Key.Z,
+                        ButtonB = Key.X,
+                        ButtonX = Key.C,
+                        ButtonY = Key.V,
+                        ButtonPlus = Key.Plus,
+                        ButtonR = Key.U,
+                        ButtonZr = Key.O,
+                        ButtonSl = Key.Unbound,
+                        ButtonSr = Key.Unbound,
+                    },
+                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = Key.I,
+                        StickDown = Key.K,
+                        StickLeft = Key.J,
+                        StickRight = Key.L,
+                        StickButton = Key.H,
+                    },
+                },
+            };
+        }
+
+        public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
+        {
+            bool configurationFileUpdated = false;
+
+            if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
+
+                LoadDefault();
+            }
+
+            if (configurationFileFormat.Version < 2)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
+
+                configurationFileFormat.SystemRegion = Region.USA;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 3)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
+
+                configurationFileFormat.SystemTimeZone = "UTC";
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 4)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
+
+                configurationFileFormat.MaxAnisotropy = -1;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 5)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
+
+                configurationFileFormat.SystemTimeOffset = 0;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 8)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
+
+                configurationFileFormat.EnablePtc = true;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 9)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
+
+                configurationFileFormat.ColumnSort = new ColumnSort
+                {
+                    SortColumnId = 0,
+                    SortAscending = false,
+                };
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = Key.F1,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 10)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
+
+                configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 11)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
+
+                configurationFileFormat.ResScale = 1;
+                configurationFileFormat.ResScaleCustom = 1.0f;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 12)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
+
+                configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
+
+                configurationFileUpdated = true;
+            }
+
+            // configurationFileFormat.Version == 13 -> LDN1
+
+            if (configurationFileFormat.Version < 14)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
+
+                configurationFileFormat.CheckUpdatesOnStart = true;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 16)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
+
+                configurationFileFormat.EnableShaderCache = true;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 17)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
+
+                configurationFileFormat.StartFullscreen = false;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 18)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
+
+                configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
+
+                configurationFileUpdated = true;
+            }
+
+            // configurationFileFormat.Version == 19 -> LDN2
+
+            if (configurationFileFormat.Version < 20)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
+
+                configurationFileFormat.ShowConfirmExit = true;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 21)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21.");
+
+                // Initialize network config.
+
+                configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled;
+                configurationFileFormat.MultiplayerLanInterfaceId = "0";
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 22)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
+
+                configurationFileFormat.HideCursor = HideCursorMode.Never;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 24)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
+
+                configurationFileFormat.InputConfig = new List<InputConfig>
+                {
+                    new StandardKeyboardInputConfig
+                    {
+                        Version = InputConfig.CurrentVersion,
+                        Backend = InputBackendType.WindowKeyboard,
+                        Id = "0",
+                        PlayerIndex = PlayerIndex.Player1,
+                        ControllerType = ControllerType.JoyconPair,
+                        LeftJoycon = new LeftJoyconCommonConfig<Key>
+                        {
+                            DpadUp = Key.Up,
+                            DpadDown = Key.Down,
+                            DpadLeft = Key.Left,
+                            DpadRight = Key.Right,
+                            ButtonMinus = Key.Minus,
+                            ButtonL = Key.E,
+                            ButtonZl = Key.Q,
+                            ButtonSl = Key.Unbound,
+                            ButtonSr = Key.Unbound,
+                        },
+                        LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
+                        {
+                            StickUp = Key.W,
+                            StickDown = Key.S,
+                            StickLeft = Key.A,
+                            StickRight = Key.D,
+                            StickButton = Key.F,
+                        },
+                        RightJoycon = new RightJoyconCommonConfig<Key>
+                        {
+                            ButtonA = Key.Z,
+                            ButtonB = Key.X,
+                            ButtonX = Key.C,
+                            ButtonY = Key.V,
+                            ButtonPlus = Key.Plus,
+                            ButtonR = Key.U,
+                            ButtonZr = Key.O,
+                            ButtonSl = Key.Unbound,
+                            ButtonSr = Key.Unbound,
+                        },
+                        RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                        {
+                            StickUp = Key.I,
+                            StickDown = Key.K,
+                            StickLeft = Key.J,
+                            StickRight = Key.L,
+                            StickButton = Key.H,
+                        },
+                    },
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 25)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 26)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
+
+                configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 27)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
+
+                configurationFileFormat.EnableMouse = false;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 28)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = Key.F1,
+                    Screenshot = Key.F8,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 29)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = Key.F1,
+                    Screenshot = Key.F8,
+                    ShowUI = Key.F4,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 30)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
+
+                foreach (InputConfig config in configurationFileFormat.InputConfig)
+                {
+                    if (config is StandardControllerInputConfig controllerConfig)
+                    {
+                        controllerConfig.Rumble = new RumbleConfigController
+                        {
+                            EnableRumble = false,
+                            StrongRumble = 1f,
+                            WeakRumble = 1f,
+                        };
+                    }
+                }
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 31)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
+
+                configurationFileFormat.BackendThreading = BackendThreading.Auto;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 32)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
+                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
+                    ShowUI = configurationFileFormat.Hotkeys.ShowUI,
+                    Pause = Key.F5,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 33)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
+                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
+                    ShowUI = configurationFileFormat.Hotkeys.ShowUI,
+                    Pause = configurationFileFormat.Hotkeys.Pause,
+                    ToggleMute = Key.F2,
+                };
+
+                configurationFileFormat.AudioVolume = 1;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 34)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
+
+                configurationFileFormat.EnableInternetAccess = false;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 35)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
+
+                foreach (InputConfig config in configurationFileFormat.InputConfig)
+                {
+                    if (config is StandardControllerInputConfig controllerConfig)
+                    {
+                        controllerConfig.RangeLeft = 1.0f;
+                        controllerConfig.RangeRight = 1.0f;
+                    }
+                }
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 36)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
+
+                configurationFileFormat.LoggingEnableTrace = false;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 37)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
+
+                configurationFileFormat.ShowConsole = true;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 38)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38.");
+
+                configurationFileFormat.BaseStyle = "Dark";
+                configurationFileFormat.GameListViewMode = 0;
+                configurationFileFormat.ShowNames = true;
+                configurationFileFormat.GridSize = 2;
+                configurationFileFormat.LanguageCode = "en_US";
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 39)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
+                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
+                    ShowUI = configurationFileFormat.Hotkeys.ShowUI,
+                    Pause = configurationFileFormat.Hotkeys.Pause,
+                    ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
+                    ResScaleUp = Key.Unbound,
+                    ResScaleDown = Key.Unbound,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 40)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40.");
+
+                configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 41)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41.");
+
+                configurationFileFormat.Hotkeys = new KeyboardHotkeys
+                {
+                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
+                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
+                    ShowUI = configurationFileFormat.Hotkeys.ShowUI,
+                    Pause = configurationFileFormat.Hotkeys.Pause,
+                    ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
+                    ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
+                    ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
+                    VolumeUp = Key.Unbound,
+                    VolumeDown = Key.Unbound,
+                };
+            }
+
+            if (configurationFileFormat.Version < 42)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
+
+                configurationFileFormat.EnableMacroHLE = true;
+            }
+
+            if (configurationFileFormat.Version < 43)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43.");
+
+                configurationFileFormat.UseHypervisor = true;
+            }
+
+            if (configurationFileFormat.Version < 44)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44.");
+
+                configurationFileFormat.AntiAliasing = AntiAliasing.None;
+                configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear;
+                configurationFileFormat.ScalingFilterLevel = 80;
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 45)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
+
+                configurationFileFormat.ShownFileTypes = new ShownFileTypes
+                {
+                    NSP = true,
+                    PFS0 = true,
+                    XCI = true,
+                    NCA = true,
+                    NRO = true,
+                    NSO = true,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 46)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
+
+                configurationFileFormat.MultiplayerLanInterfaceId = "0";
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 47)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
+
+                configurationFileFormat.WindowStartup = new WindowStartup
+                {
+                    WindowPositionX = 0,
+                    WindowPositionY = 0,
+                    WindowSizeHeight = 760,
+                    WindowSizeWidth = 1280,
+                    WindowMaximized = false,
+                };
+
+                configurationFileUpdated = true;
+            }
+
+            if (configurationFileFormat.Version < 48)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
+
+                configurationFileFormat.EnableColorSpacePassthrough = false;
+
+                configurationFileUpdated = true;
+            }
+
+            Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
+            Graphics.ResScale.Value = configurationFileFormat.ResScale;
+            Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
+            Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
+            Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
+            Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
+            Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
+            Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend;
+            Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu;
+            Graphics.AntiAliasing.Value = configurationFileFormat.AntiAliasing;
+            Graphics.ScalingFilter.Value = configurationFileFormat.ScalingFilter;
+            Graphics.ScalingFilterLevel.Value = configurationFileFormat.ScalingFilterLevel;
+            Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
+            Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
+            Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
+            Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
+            Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
+            Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
+            Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
+            Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
+            Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
+            Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
+            System.Language.Value = configurationFileFormat.SystemLanguage;
+            System.Region.Value = configurationFileFormat.SystemRegion;
+            System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
+            System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
+            System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
+            EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
+            CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
+            ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
+            HideCursor.Value = configurationFileFormat.HideCursor;
+            Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
+            Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
+            Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
+            Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
+            Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
+            System.EnablePtc.Value = configurationFileFormat.EnablePtc;
+            System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
+            System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
+            System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
+            System.AudioBackend.Value = configurationFileFormat.AudioBackend;
+            System.AudioVolume.Value = configurationFileFormat.AudioVolume;
+            System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
+            System.ExpandRam.Value = configurationFileFormat.ExpandRam;
+            System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
+            System.UseHypervisor.Value = configurationFileFormat.UseHypervisor;
+            UI.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
+            UI.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
+            UI.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
+            UI.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
+            UI.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
+            UI.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
+            UI.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
+            UI.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
+            UI.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
+            UI.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
+            UI.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
+            UI.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
+            UI.GameDirs.Value = configurationFileFormat.GameDirs;
+            UI.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP;
+            UI.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0;
+            UI.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI;
+            UI.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA;
+            UI.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO;
+            UI.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO;
+            UI.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
+            UI.LanguageCode.Value = configurationFileFormat.LanguageCode;
+            UI.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
+            UI.BaseStyle.Value = configurationFileFormat.BaseStyle;
+            UI.GameListViewMode.Value = configurationFileFormat.GameListViewMode;
+            UI.ShowNames.Value = configurationFileFormat.ShowNames;
+            UI.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder;
+            UI.GridSize.Value = configurationFileFormat.GridSize;
+            UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
+            UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
+            UI.ShowConsole.Value = configurationFileFormat.ShowConsole;
+            UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth;
+            UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight;
+            UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX;
+            UI.WindowStartup.WindowPositionY.Value = configurationFileFormat.WindowStartup.WindowPositionY;
+            UI.WindowStartup.WindowMaximized.Value = configurationFileFormat.WindowStartup.WindowMaximized;
+            Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
+            Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
+            Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
+            Hid.InputConfig.Value = configurationFileFormat.InputConfig;
+
+            if (Hid.InputConfig.Value == null)
+            {
+                Hid.InputConfig.Value = new List<InputConfig>();
+            }
+
+            Multiplayer.LanInterfaceId.Value = configurationFileFormat.MultiplayerLanInterfaceId;
+            Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
+
+            if (configurationFileUpdated)
+            {
+                ToFileFormat().SaveConfig(configurationFilePath);
+
+                Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
+            }
+        }
+
+        private static GraphicsBackend DefaultGraphicsBackend()
+        {
+            // Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
+            // Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
+            if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
+            {
+                return GraphicsBackend.Vulkan;
+            }
+
+            return GraphicsBackend.OpenGl;
+        }
+
+        private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName)
+        {
+            Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
+        }
+
+        public static void Initialize()
+        {
+            if (Instance != null)
+            {
+                throw new InvalidOperationException("Configuration is already initialized");
+            }
+
+            Instance = new ConfigurationState();
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/FileTypes.cs b/src/Ryujinx.UI.Common/Configuration/FileTypes.cs
new file mode 100644
index 00000000..1974207b
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/FileTypes.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.UI.Common
+{
+    public enum FileTypes
+    {
+        NSP,
+        PFS0,
+        XCI,
+        NCA,
+        NRO,
+        NSO
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs b/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs
new file mode 100644
index 00000000..9cb28359
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs
@@ -0,0 +1,113 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Logging.Targets;
+using System;
+using System.IO;
+
+namespace Ryujinx.UI.Common.Configuration
+{
+    public static class LoggerModule
+    {
+        public static void Initialize()
+        {
+            ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug;
+            ConfigurationState.Instance.Logger.EnableStub.Event += ReloadEnableStub;
+            ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo;
+            ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning;
+            ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError;
+            ConfigurationState.Instance.Logger.EnableTrace.Event += ReloadEnableTrace;
+            ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest;
+            ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog;
+            ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses;
+            ConfigurationState.Instance.Logger.EnableFileLog.Event += ReloadFileLogger;
+        }
+
+        private static void ReloadEnableDebug(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Debug, e.NewValue);
+        }
+
+        private static void ReloadEnableStub(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Stub, e.NewValue);
+        }
+
+        private static void ReloadEnableInfo(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Info, e.NewValue);
+        }
+
+        private static void ReloadEnableWarning(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Warning, e.NewValue);
+        }
+
+        private static void ReloadEnableError(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Error, e.NewValue);
+        }
+
+        private static void ReloadEnableTrace(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Trace, e.NewValue);
+        }
+
+        private static void ReloadEnableGuest(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.Guest, e.NewValue);
+        }
+
+        private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs<bool> e)
+        {
+            Logger.SetEnable(LogLevel.AccessLog, e.NewValue);
+        }
+
+        private static void ReloadFilteredClasses(object sender, ReactiveEventArgs<LogClass[]> e)
+        {
+            bool noFilter = e.NewValue.Length == 0;
+
+            foreach (var logClass in Enum.GetValues<LogClass>())
+            {
+                Logger.SetEnable(logClass, noFilter);
+            }
+
+            foreach (var logClass in e.NewValue)
+            {
+                Logger.SetEnable(logClass, true);
+            }
+        }
+
+        private static void ReloadFileLogger(object sender, ReactiveEventArgs<bool> e)
+        {
+            if (e.NewValue)
+            {
+                string logDir = AppDataManager.LogsDirPath;
+                FileStream logFile = null;
+
+                if (!string.IsNullOrEmpty(logDir))
+                {
+                    logFile = FileLogTarget.PrepareLogFile(logDir);
+                }
+
+                if (logFile == null)
+                {
+                    Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable.");
+                    Logger.RemoveTarget("file");
+
+                    return;
+                }
+
+                Logger.AddTarget(new AsyncLogTargetWrapper(
+                    new FileLogTarget("file", logFile),
+                    1000,
+                    AsyncLogTargetOverflowAction.Block
+                ));
+            }
+            else
+            {
+                Logger.RemoveTarget("file");
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/System/Language.cs b/src/Ryujinx.UI.Common/Configuration/System/Language.cs
new file mode 100644
index 00000000..d1d395b0
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/System/Language.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Common.Utilities;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Configuration.System
+{
+    [JsonConverter(typeof(TypedStringEnumConverter<Language>))]
+    public enum Language
+    {
+        Japanese,
+        AmericanEnglish,
+        French,
+        German,
+        Italian,
+        Spanish,
+        Chinese,
+        Korean,
+        Dutch,
+        Portuguese,
+        Russian,
+        Taiwanese,
+        BritishEnglish,
+        CanadianFrench,
+        LatinAmericanSpanish,
+        SimplifiedChinese,
+        TraditionalChinese,
+        BrazilianPortuguese,
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/System/Region.cs b/src/Ryujinx.UI.Common/Configuration/System/Region.cs
new file mode 100644
index 00000000..6087c70e
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/System/Region.cs
@@ -0,0 +1,17 @@
+using Ryujinx.Common.Utilities;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Configuration.System
+{
+    [JsonConverter(typeof(TypedStringEnumConverter<Region>))]
+    public enum Region
+    {
+        Japan,
+        USA,
+        Europe,
+        Australia,
+        China,
+        Korea,
+        Taiwan,
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs b/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs
new file mode 100644
index 00000000..44e98c40
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.UI.Common.Configuration.UI
+{
+    public struct ColumnSort
+    {
+        public int SortColumnId { get; set; }
+        public bool SortAscending { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs b/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs
new file mode 100644
index 00000000..c778ef1f
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs
@@ -0,0 +1,16 @@
+namespace Ryujinx.UI.Common.Configuration.UI
+{
+    public struct GuiColumns
+    {
+        public bool FavColumn { get; set; }
+        public bool IconColumn { get; set; }
+        public bool AppColumn { get; set; }
+        public bool DevColumn { get; set; }
+        public bool VersionColumn { get; set; }
+        public bool TimePlayedColumn { get; set; }
+        public bool LastPlayedColumn { get; set; }
+        public bool FileExtColumn { get; set; }
+        public bool FileSizeColumn { get; set; }
+        public bool PathColumn { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs b/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs
new file mode 100644
index 00000000..6c72a693
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.UI.Common.Configuration.UI
+{
+    public struct ShownFileTypes
+    {
+        public bool NSP { get; set; }
+        public bool PFS0 { get; set; }
+        public bool XCI { get; set; }
+        public bool NCA { get; set; }
+        public bool NRO { get; set; }
+        public bool NSO { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs b/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs
new file mode 100644
index 00000000..0df45913
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.UI.Common.Configuration.UI
+{
+    public struct WindowStartup
+    {
+        public int WindowSizeWidth { get; set; }
+        public int WindowSizeHeight { get; set; }
+        public int WindowPositionX { get; set; }
+        public int WindowPositionY { get; set; }
+        public bool WindowMaximized { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
new file mode 100644
index 00000000..0b9439ea
--- /dev/null
+++ b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
@@ -0,0 +1,98 @@
+using DiscordRPC;
+using Ryujinx.Common;
+using Ryujinx.UI.Common.Configuration;
+
+namespace Ryujinx.UI.Common
+{
+    public static class DiscordIntegrationModule
+    {
+        private const string Description = "A simple, experimental Nintendo Switch emulator.";
+        private const string CliendId = "568815339807309834";
+
+        private static DiscordRpcClient _discordClient;
+        private static RichPresence _discordPresenceMain;
+
+        public static void Initialize()
+        {
+            _discordPresenceMain = new RichPresence
+            {
+                Assets = new Assets
+                {
+                    LargeImageKey = "ryujinx",
+                    LargeImageText = Description,
+                },
+                Details = "Main Menu",
+                State = "Idling",
+                Timestamps = Timestamps.Now,
+                Buttons = new[]
+                {
+                    new Button
+                    {
+                        Label = "Website",
+                        Url   = "https://ryujinx.org/",
+                    },
+                },
+            };
+
+            ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
+        }
+
+        private static void Update(object sender, ReactiveEventArgs<bool> evnt)
+        {
+            if (evnt.OldValue != evnt.NewValue)
+            {
+                // If the integration was active, disable it and unload everything
+                if (evnt.OldValue)
+                {
+                    _discordClient?.Dispose();
+
+                    _discordClient = null;
+                }
+
+                // If we need to activate it and the client isn't active, initialize it
+                if (evnt.NewValue && _discordClient == null)
+                {
+                    _discordClient = new DiscordRpcClient(CliendId);
+
+                    _discordClient.Initialize();
+                    _discordClient.SetPresence(_discordPresenceMain);
+                }
+            }
+        }
+
+        public static void SwitchToPlayingState(string titleId, string titleName)
+        {
+            _discordClient?.SetPresence(new RichPresence
+            {
+                Assets = new Assets
+                {
+                    LargeImageKey = "game",
+                    LargeImageText = titleName,
+                    SmallImageKey = "ryujinx",
+                    SmallImageText = Description,
+                },
+                Details = $"Playing {titleName}",
+                State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
+                Timestamps = Timestamps.Now,
+                Buttons = new[]
+                {
+                    new Button
+                    {
+                        Label = "Website",
+                        Url = "https://ryujinx.org/",
+                    },
+                },
+            });
+        }
+
+        public static void SwitchToMainMenu()
+        {
+            _discordClient?.SetPresence(_discordPresenceMain);
+        }
+
+        public static void Exit()
+        {
+            _discordClient?.Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs b/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs
new file mode 100644
index 00000000..7e71ba7a
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs
@@ -0,0 +1,25 @@
+using System;
+using static Ryujinx.UI.Common.Configuration.ConfigurationState.UISection;
+
+namespace Ryujinx.UI.Common
+{
+    public static class FileTypesExtensions
+    {
+        /// <summary>
+        /// Gets the current <see cref="ShownFileTypeSettings"/> value for the correlating FileType name.
+        /// </summary>
+        /// <param name="type">The name of the <see cref="ShownFileTypeSettings"/> parameter to get the value of.</param>
+        /// <param name="config">The config instance to get the value from.</param>
+        /// <returns>The current value of the setting. Value is <see langword="true"/> if the file type is the be shown on the games list, <see langword="false"/> otherwise.</returns>
+        public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch
+        {
+            FileTypes.NSP => config.NSP.Value,
+            FileTypes.PFS0 => config.PFS0.Value,
+            FileTypes.XCI => config.XCI.Value,
+            FileTypes.NCA => config.NCA.Value,
+            FileTypes.NRO => config.NRO.Value,
+            FileTypes.NSO => config.NSO.Value,
+            _ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
+        };
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/CommandLineState.cs b/src/Ryujinx.UI.Common/Helper/CommandLineState.cs
new file mode 100644
index 00000000..c3c5bd37
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/CommandLineState.cs
@@ -0,0 +1,99 @@
+using Ryujinx.Common.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static class CommandLineState
+    {
+        public static string[] Arguments { get; private set; }
+
+        public static bool? OverrideDockedMode { get; private set; }
+        public static string OverrideGraphicsBackend { get; private set; }
+        public static string OverrideHideCursor { get; private set; }
+        public static string BaseDirPathArg { get; private set; }
+        public static string Profile { get; private set; }
+        public static string LaunchPathArg { get; private set; }
+        public static bool StartFullscreenArg { get; private set; }
+
+        public static void ParseArguments(string[] args)
+        {
+            List<string> arguments = new();
+
+            // Parse Arguments.
+            for (int i = 0; i < args.Length; ++i)
+            {
+                string arg = args[i];
+
+                switch (arg)
+                {
+                    case "-r":
+                    case "--root-data-dir":
+                        if (i + 1 >= args.Length)
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
+
+                            continue;
+                        }
+
+                        BaseDirPathArg = args[++i];
+
+                        arguments.Add(arg);
+                        arguments.Add(args[i]);
+                        break;
+                    case "-p":
+                    case "--profile":
+                        if (i + 1 >= args.Length)
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
+
+                            continue;
+                        }
+
+                        Profile = args[++i];
+
+                        arguments.Add(arg);
+                        arguments.Add(args[i]);
+                        break;
+                    case "-f":
+                    case "--fullscreen":
+                        StartFullscreenArg = true;
+
+                        arguments.Add(arg);
+                        break;
+                    case "-g":
+                    case "--graphics-backend":
+                        if (i + 1 >= args.Length)
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
+
+                            continue;
+                        }
+
+                        OverrideGraphicsBackend = args[++i];
+                        break;
+                    case "--docked-mode":
+                        OverrideDockedMode = true;
+                        break;
+                    case "--handheld-mode":
+                        OverrideDockedMode = false;
+                        break;
+                    case "--hide-cursor":
+                        if (i + 1 >= args.Length)
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
+
+                            continue;
+                        }
+
+                        OverrideHideCursor = args[++i];
+                        break;
+                    default:
+                        LaunchPathArg = arg;
+                        break;
+                }
+            }
+
+            Arguments = arguments.ToArray();
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs b/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs
new file mode 100644
index 00000000..208ff5c9
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs
@@ -0,0 +1,50 @@
+using Ryujinx.Common.Logging;
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static partial class ConsoleHelper
+    {
+        public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
+
+        public static void SetConsoleWindowState(bool show)
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                SetConsoleWindowStateWindows(show);
+            }
+            else if (show == false)
+            {
+                Logger.Warning?.Print(LogClass.Application, "OS doesn't support hiding console window");
+            }
+        }
+
+        [SupportedOSPlatform("windows")]
+        private static void SetConsoleWindowStateWindows(bool show)
+        {
+            const int SW_HIDE = 0;
+            const int SW_SHOW = 5;
+
+            IntPtr hWnd = GetConsoleWindow();
+
+            if (hWnd == IntPtr.Zero)
+            {
+                Logger.Warning?.Print(LogClass.Application, "Attempted to show/hide console window but console window does not exist");
+                return;
+            }
+
+            ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
+        }
+
+        [SupportedOSPlatform("windows")]
+        [LibraryImport("kernel32")]
+        private static partial IntPtr GetConsoleWindow();
+
+        [SupportedOSPlatform("windows")]
+        [LibraryImport("user32")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static partial bool ShowWindow(IntPtr hWnd, int nCmdShow);
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
new file mode 100644
index 00000000..7ed02031
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
@@ -0,0 +1,202 @@
+using Microsoft.Win32;
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static partial class FileAssociationHelper
+    {
+        private static readonly string[] _fileExtensions = { ".nca", ".nro", ".nso", ".nsp", ".xci" };
+
+        [SupportedOSPlatform("linux")]
+        private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
+
+        private const int SHCNE_ASSOCCHANGED = 0x8000000;
+        private const int SHCNF_FLUSH = 0x1000;
+
+        [LibraryImport("shell32.dll", SetLastError = true)]
+        public static partial void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
+
+        public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild;
+
+        [SupportedOSPlatform("linux")]
+        private static bool AreMimeTypesRegisteredLinux() => File.Exists(Path.Combine(_mimeDbPath, "packages", "Ryujinx.xml"));
+
+        [SupportedOSPlatform("linux")]
+        private static bool InstallLinuxMimeTypes(bool uninstall = false)
+        {
+            string installKeyword = uninstall ? "uninstall" : "install";
+
+            if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux()))
+            {
+                string mimeTypesFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mime", "Ryujinx.xml");
+                string additionalArgs = !uninstall ? "--novendor" : "";
+
+                using Process mimeProcess = new();
+
+                mimeProcess.StartInfo.FileName = "xdg-mime";
+                mimeProcess.StartInfo.Arguments = $"{installKeyword} {additionalArgs} --mode user {mimeTypesFile}";
+
+                mimeProcess.Start();
+                mimeProcess.WaitForExit();
+
+                if (mimeProcess.ExitCode != 0)
+                {
+                    Logger.Error?.PrintMsg(LogClass.Application, $"Unable to {installKeyword} mime types. Make sure xdg-utils is installed. Process exited with code: {mimeProcess.ExitCode}");
+
+                    return false;
+                }
+
+                using Process updateMimeProcess = new();
+
+                updateMimeProcess.StartInfo.FileName = "update-mime-database";
+                updateMimeProcess.StartInfo.Arguments = _mimeDbPath;
+
+                updateMimeProcess.Start();
+                updateMimeProcess.WaitForExit();
+
+                if (updateMimeProcess.ExitCode != 0)
+                {
+                    Logger.Error?.PrintMsg(LogClass.Application, $"Could not update local mime database. Process exited with code: {updateMimeProcess.ExitCode}");
+                }
+            }
+
+            return true;
+        }
+
+        [SupportedOSPlatform("windows")]
+        private static bool AreMimeTypesRegisteredWindows()
+        {
+            static bool CheckRegistering(string ext)
+            {
+                RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}");
+
+                if (key is null)
+                {
+                    return false;
+                }
+
+                var openCmd = key.OpenSubKey(@"shell\open\command");
+
+                string keyValue = (string)openCmd.GetValue("");
+
+                return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
+            }
+
+            bool registered = false;
+
+            foreach (string ext in _fileExtensions)
+            {
+                registered |= CheckRegistering(ext);
+            }
+
+            return registered;
+        }
+
+        [SupportedOSPlatform("windows")]
+        private static bool InstallWindowsMimeTypes(bool uninstall = false)
+        {
+            static bool RegisterExtension(string ext, bool uninstall = false)
+            {
+                string keyString = @$"Software\Classes\{ext}";
+
+                if (uninstall)
+                {
+                    // If the types don't already exist, there's nothing to do and we can call this operation successful.
+                    if (!AreMimeTypesRegisteredWindows())
+                    {
+                        return true;
+                    }
+                    Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
+                    Registry.CurrentUser.DeleteSubKeyTree(keyString);
+                    Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
+                }
+                else
+                {
+                    using var key = Registry.CurrentUser.CreateSubKey(keyString);
+
+                    if (key is null)
+                    {
+                        return false;
+                    }
+
+                    Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
+                    using var openCmd = key.CreateSubKey(@"shell\open\command");
+                    openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
+                    Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
+
+                }
+
+                return true;
+            }
+
+            bool registered = false;
+
+            foreach (string ext in _fileExtensions)
+            {
+                registered |= RegisterExtension(ext, uninstall);
+            }
+
+            // Notify Explorer the file association has been changed.
+            SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
+
+            return registered;
+        }
+
+        public static bool AreMimeTypesRegistered()
+        {
+            if (OperatingSystem.IsLinux())
+            {
+                return AreMimeTypesRegisteredLinux();
+            }
+
+            if (OperatingSystem.IsWindows())
+            {
+                return AreMimeTypesRegisteredWindows();
+            }
+
+            // TODO: Add macOS support.
+
+            return false;
+        }
+
+        public static bool Install()
+        {
+            if (OperatingSystem.IsLinux())
+            {
+                return InstallLinuxMimeTypes();
+            }
+
+            if (OperatingSystem.IsWindows())
+            {
+                return InstallWindowsMimeTypes();
+            }
+
+            // TODO: Add macOS support.
+
+            return false;
+        }
+
+        public static bool Uninstall()
+        {
+            if (OperatingSystem.IsLinux())
+            {
+                return InstallLinuxMimeTypes(true);
+            }
+
+            if (OperatingSystem.IsWindows())
+            {
+                return InstallWindowsMimeTypes(true);
+            }
+
+            // TODO: Add macOS support.
+
+            return false;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs b/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs
new file mode 100644
index 00000000..b5779379
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    [SupportedOSPlatform("linux")]
+    public static class LinuxHelper
+    {
+        // NOTE: This value was determined by manual tests and might need to be increased again.
+        public const int RecommendedVmMaxMapCount = 524288;
+        public const string VmMaxMapCountPath = "/proc/sys/vm/max_map_count";
+        public const string SysCtlConfigPath = "/etc/sysctl.d/99-Ryujinx.conf";
+        public static int VmMaxMapCount => int.Parse(File.ReadAllText(VmMaxMapCountPath));
+        public static string PkExecPath { get; } = GetBinaryPath("pkexec");
+
+        private static string GetBinaryPath(string binary)
+        {
+            string pathVar = Environment.GetEnvironmentVariable("PATH");
+
+            if (pathVar is null || string.IsNullOrEmpty(binary))
+            {
+                return null;
+            }
+
+            foreach (var searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
+            {
+                string binaryPath = Path.Combine(searchPath, binary);
+
+                if (File.Exists(binaryPath))
+                {
+                    return binaryPath;
+                }
+            }
+
+            return null;
+        }
+
+        public static int RunPkExec(string command)
+        {
+            if (PkExecPath == null)
+            {
+                return 1;
+            }
+
+            using Process process = new()
+            {
+                StartInfo =
+                {
+                    FileName = PkExecPath,
+                    ArgumentList = { "sh", "-c", command },
+                },
+            };
+
+            process.Start();
+            process.WaitForExit();
+
+            return process.ExitCode;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs b/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs
new file mode 100644
index 00000000..6aba377a
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    [SupportedOSPlatform("macos")]
+    public static partial class ObjectiveC
+    {
+        private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
+
+        [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
+        private static partial IntPtr sel_getUid(string name);
+
+        [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
+        private static partial IntPtr objc_getClass(string name);
+
+        [LibraryImport(ObjCRuntime)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector);
+
+        [LibraryImport(ObjCRuntime)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
+
+        [LibraryImport(ObjCRuntime)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
+
+        [LibraryImport(ObjCRuntime)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
+
+        [LibraryImport(ObjCRuntime)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
+
+        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
+
+        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
+
+        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
+        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
+
+        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
+
+        public readonly struct Object
+        {
+            public readonly IntPtr ObjPtr;
+
+            private Object(IntPtr pointer)
+            {
+                ObjPtr = pointer;
+            }
+
+            public Object(string name)
+            {
+                ObjPtr = objc_getClass(name);
+            }
+
+            public void SendMessage(Selector selector)
+            {
+                objc_msgSend(ObjPtr, selector);
+            }
+
+            public void SendMessage(Selector selector, byte value)
+            {
+                objc_msgSend(ObjPtr, selector, value);
+            }
+
+            public void SendMessage(Selector selector, Object obj)
+            {
+                objc_msgSend(ObjPtr, selector, obj.ObjPtr);
+            }
+
+            public void SendMessage(Selector selector, NSRect point)
+            {
+                objc_msgSend(ObjPtr, selector, point);
+            }
+
+            public void SendMessage(Selector selector, double value)
+            {
+                objc_msgSend(ObjPtr, selector, value);
+            }
+
+            public Object GetFromMessage(Selector selector)
+            {
+                return new Object(IntPtr_objc_msgSend(ObjPtr, selector));
+            }
+
+            public Object GetFromMessage(Selector selector, Object obj)
+            {
+                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, obj.ObjPtr));
+            }
+
+            public Object GetFromMessage(Selector selector, NSString nsString)
+            {
+                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, nsString.StrPtr));
+            }
+
+            public Object GetFromMessage(Selector selector, string param)
+            {
+                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, param));
+            }
+
+            public bool GetBoolFromMessage(Selector selector, Object obj)
+            {
+                return bool_objc_msgSend(ObjPtr, selector, obj.ObjPtr);
+            }
+        }
+
+        public readonly struct Selector
+        {
+            public readonly IntPtr SelPtr;
+
+            private Selector(string name)
+            {
+                SelPtr = sel_getUid(name);
+            }
+
+            public static implicit operator Selector(string value) => new(value);
+        }
+
+        public readonly struct NSString
+        {
+            public readonly IntPtr StrPtr;
+
+            public NSString(string aString)
+            {
+                IntPtr nsString = objc_getClass("NSString");
+                StrPtr = IntPtr_objc_msgSend(nsString, "stringWithUTF8String:", aString);
+            }
+
+            public static implicit operator IntPtr(NSString nsString) => nsString.StrPtr;
+        }
+
+        public readonly struct NSPoint
+        {
+            public readonly double X;
+            public readonly double Y;
+
+            public NSPoint(double x, double y)
+            {
+                X = x;
+                Y = y;
+            }
+        }
+
+        public readonly struct NSRect
+        {
+            public readonly NSPoint Pos;
+            public readonly NSPoint Size;
+
+            public NSRect(double x, double y, double width, double height)
+            {
+                Pos = new NSPoint(x, y);
+                Size = new NSPoint(width, height);
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/OpenHelper.cs b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs
new file mode 100644
index 00000000..af6170af
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs
@@ -0,0 +1,112 @@
+using Ryujinx.Common.Logging;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static partial class OpenHelper
+    {
+        [LibraryImport("shell32.dll", SetLastError = true)]
+        private static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
+
+        [LibraryImport("shell32.dll", SetLastError = true)]
+        private static partial void ILFree(IntPtr pidlList);
+
+        [LibraryImport("shell32.dll", SetLastError = true)]
+        private static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath);
+
+        public static void OpenFolder(string path)
+        {
+            if (Directory.Exists(path))
+            {
+                Process.Start(new ProcessStartInfo
+                {
+                    FileName = path,
+                    UseShellExecute = true,
+                    Verb = "open",
+                });
+            }
+            else
+            {
+                Logger.Notice.Print(LogClass.Application, $"Directory \"{path}\" doesn't exist!");
+            }
+        }
+
+        public static void LocateFile(string path)
+        {
+            if (File.Exists(path))
+            {
+                if (OperatingSystem.IsWindows())
+                {
+                    IntPtr pidlList = ILCreateFromPathW(path);
+                    if (pidlList != IntPtr.Zero)
+                    {
+                        try
+                        {
+                            Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0));
+                        }
+                        finally
+                        {
+                            ILFree(pidlList);
+                        }
+                    }
+                }
+                else if (OperatingSystem.IsMacOS())
+                {
+                    ObjectiveC.NSString nsStringPath = new(path);
+                    ObjectiveC.Object nsUrl = new("NSURL");
+                    var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
+
+                    ObjectiveC.Object nsArray = new("NSArray");
+                    ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
+
+                    ObjectiveC.Object nsWorkspace = new("NSWorkspace");
+                    ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
+
+                    sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray);
+                }
+                else if (OperatingSystem.IsLinux())
+                {
+                    Process.Start("dbus-send", $"--session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:\"file://{path}\" string:\"\"");
+                }
+                else
+                {
+                    OpenFolder(Path.GetDirectoryName(path));
+                }
+            }
+            else
+            {
+                Logger.Notice.Print(LogClass.Application, $"File \"{path}\" doesn't exist!");
+            }
+        }
+
+        public static void OpenUrl(string url)
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                Process.Start(new ProcessStartInfo("cmd", $"/c start {url.Replace("&", "^&")}"));
+            }
+            else if (OperatingSystem.IsLinux())
+            {
+                Process.Start("xdg-open", url);
+            }
+            else if (OperatingSystem.IsMacOS())
+            {
+                ObjectiveC.NSString nsStringPath = new(url);
+                ObjectiveC.Object nsUrl = new("NSURL");
+                var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
+
+                ObjectiveC.Object nsWorkspace = new("NSWorkspace");
+                ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
+
+                sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr);
+            }
+            else
+            {
+                Logger.Notice.Print(LogClass.Application, $"Cannot open url \"{url}\" on this platform!");
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/SetupValidator.cs b/src/Ryujinx.UI.Common/Helper/SetupValidator.cs
new file mode 100644
index 00000000..a954be26
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/SetupValidator.cs
@@ -0,0 +1,114 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.FileSystem;
+using System;
+using System.IO;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    /// <summary>
+    /// Ensure installation validity
+    /// </summary>
+    public static class SetupValidator
+    {
+        public static bool IsFirmwareValid(ContentManager contentManager, out UserError error)
+        {
+            bool hasFirmware = contentManager.GetCurrentFirmwareVersion() != null;
+
+            if (hasFirmware)
+            {
+                error = UserError.Success;
+
+                return true;
+            }
+
+            error = UserError.NoFirmware;
+
+            return false;
+        }
+
+        public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion)
+        {
+            try
+            {
+                firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath);
+            }
+            catch (Exception)
+            {
+                firmwareVersion = null;
+            }
+
+            return error == UserError.NoFirmware && Path.GetExtension(baseApplicationPath).ToLowerInvariant() == ".xci" && firmwareVersion != null;
+        }
+
+        public static bool TryFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out UserError outError)
+        {
+            if (error == UserError.NoFirmware)
+            {
+                string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant();
+
+                // If the target app to start is a XCI, try to install firmware from it
+                if (baseApplicationExtension == ".xci")
+                {
+                    SystemVersion firmwareVersion;
+
+                    try
+                    {
+                        firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath);
+                    }
+                    catch (Exception)
+                    {
+                        firmwareVersion = null;
+                    }
+
+                    // The XCI is a valid firmware package, try to install the firmware from it!
+                    if (firmwareVersion != null)
+                    {
+                        try
+                        {
+                            Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
+
+                            contentManager.InstallFirmware(baseApplicationPath);
+
+                            Logger.Info?.Print(LogClass.Application, $"System version {firmwareVersion.VersionString} successfully installed.");
+
+                            outError = UserError.Success;
+
+                            return true;
+                        }
+                        catch (Exception) { }
+                    }
+
+                    outError = error;
+
+                    return false;
+                }
+            }
+
+            outError = error;
+
+            return false;
+        }
+
+        public static bool CanStartApplication(ContentManager contentManager, string baseApplicationPath, out UserError error)
+        {
+            if (Directory.Exists(baseApplicationPath) || File.Exists(baseApplicationPath))
+            {
+                string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant();
+
+                // NOTE: We don't force homebrew developers to install a system firmware.
+                if (baseApplicationExtension == ".nro" || baseApplicationExtension == ".nso")
+                {
+                    error = UserError.Success;
+
+                    return true;
+                }
+
+                return IsFirmwareValid(contentManager, out error);
+            }
+
+            error = UserError.ApplicationNotFound;
+
+            return false;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
new file mode 100644
index 00000000..c2085b28
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
@@ -0,0 +1,162 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using ShellLink;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static class ShortcutHelper
+    {
+        [SupportedOSPlatform("windows")]
+        private static void CreateShortcutWindows(string applicationFilePath, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
+        {
+            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
+            iconPath += ".ico";
+
+            MemoryStream iconDataStream = new(iconData);
+            var image = Image.Load(iconDataStream);
+            image.Mutate(x => x.Resize(128, 128));
+            SaveBitmapAsIcon(image, iconPath);
+
+            var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
+            shortcut.StringData.NameString = cleanedAppName;
+            shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
+        }
+
+        [SupportedOSPlatform("linux")]
+        private static void CreateShortcutLinux(string applicationFilePath, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
+        {
+            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
+            var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop");
+            iconPath += ".png";
+
+            var image = Image.Load<Rgba32>(iconData);
+            image.SaveAsPng(iconPath);
+
+            using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
+            outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath)}");
+        }
+
+        [SupportedOSPlatform("macos")]
+        private static void CreateShortcutMacos(string appFilePath, byte[] iconData, string desktopPath, string cleanedAppName)
+        {
+            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
+            var plistFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.plist");
+            var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-launch-script.sh");
+            // Macos .App folder
+            string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents");
+            string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS");
+
+            if (!Directory.Exists(scriptFolderPath))
+            {
+                Directory.CreateDirectory(scriptFolderPath);
+            }
+
+            // Runner script
+            const string ScriptName = "runner.sh";
+            string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
+            using StreamWriter scriptFile = new(scriptPath);
+
+            scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath));
+
+            // Set execute permission
+            FileInfo fileInfo = new(scriptPath);
+            fileInfo.UnixFileMode |= UnixFileMode.UserExecute;
+
+            // img
+            string resourceFolderPath = Path.Combine(contentFolderPath, "Resources");
+            if (!Directory.Exists(resourceFolderPath))
+            {
+                Directory.CreateDirectory(resourceFolderPath);
+            }
+
+            const string IconName = "icon.png";
+            var image = Image.Load<Rgba32>(iconData);
+            image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
+
+            // plist file
+            using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
+            outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
+        }
+
+        public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
+        {
+            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
+            string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
+
+            if (OperatingSystem.IsWindows())
+            {
+                string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
+
+                CreateShortcutWindows(applicationFilePath, iconData, iconPath, cleanedAppName, desktopPath);
+
+                return;
+            }
+
+            if (OperatingSystem.IsLinux())
+            {
+                string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
+
+                Directory.CreateDirectory(iconPath);
+                CreateShortcutLinux(applicationFilePath, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
+
+                return;
+            }
+
+            if (OperatingSystem.IsMacOS())
+            {
+                CreateShortcutMacos(applicationFilePath, iconData, desktopPath, cleanedAppName);
+
+                return;
+            }
+
+            throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
+        }
+
+        private static string GetArgsString(string appFilePath)
+        {
+            // args are first defined as a list, for easier adjustments in the future
+            var argsList = new List<string>();
+
+            if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg))
+            {
+                argsList.Add("--root-data-dir");
+                argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
+            }
+
+            argsList.Add($"\"{appFilePath}\"");
+
+            return String.Join(" ", argsList);
+        }
+
+        /// <summary>
+        /// Creates a Icon (.ico) file using the source bitmap image at the specified file path.
+        /// </summary>
+        /// <param name="source">The source bitmap image that will be saved as an .ico file</param>
+        /// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
+        [SupportedOSPlatform("windows")]
+        private static void SaveBitmapAsIcon(Image source, string filePath)
+        {
+            // Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
+            byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
+            using FileStream fs = new(filePath, FileMode.Create);
+
+            fs.Write(header);
+            // Writing actual data
+            source.Save(fs, PngFormat.Instance);
+            // Getting data length (file length minus header)
+            long dataLength = fs.Length - header.Length;
+            // Write it in the correct place
+            fs.Seek(14, SeekOrigin.Begin);
+            fs.WriteByte((byte)dataLength);
+            fs.WriteByte((byte)(dataLength >> 8));
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/TitleHelper.cs b/src/Ryujinx.UI.Common/Helper/TitleHelper.cs
new file mode 100644
index 00000000..8b47ac38
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/TitleHelper.cs
@@ -0,0 +1,30 @@
+using Ryujinx.HLE.Loaders.Processes;
+using System;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static class TitleHelper
+    {
+        public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, string pauseString = "")
+        {
+            if (activeProcess == null)
+            {
+                return String.Empty;
+            }
+
+            string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
+            string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
+            string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
+            string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
+
+            string appTitle = $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
+
+            if (!string.IsNullOrEmpty(pauseString))
+            {
+                appTitle += $" ({pauseString})";
+            }
+
+            return appTitle;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs b/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs
new file mode 100644
index 00000000..8ea3e721
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace Ryujinx.UI.Common.Helper
+{
+    public static class ValueFormatUtils
+    {
+        private static readonly string[] _fileSizeUnitStrings =
+        {
+            "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",  // Base 10 units, used for formatting and parsing
+            "KB", "MB", "GB", "TB", "PB", "EB",             // Base 2 units, used for parsing legacy values
+        };
+
+        /// <summary>
+        /// Used by <see cref="FormatFileSize"/>.
+        /// </summary>
+        public enum FileSizeUnits
+        {
+            Auto = -1,
+            Bytes = 0,
+            Kibibytes = 1,
+            Mebibytes = 2,
+            Gibibytes = 3,
+            Tebibytes = 4,
+            Pebibytes = 5,
+            Exbibytes = 6,
+            Kilobytes = 7,
+            Megabytes = 8,
+            Gigabytes = 9,
+            Terabytes = 10,
+            Petabytes = 11,
+            Exabytes = 12,
+        }
+
+        private const double SizeBase10 = 1000;
+        private const double SizeBase2 = 1024;
+        private const int UnitEBIndex = 6;
+
+        #region Value formatters
+
+        /// <summary>
+        /// Creates a human-readable string from a <see cref="TimeSpan"/>.
+        /// </summary>
+        /// <param name="timeSpan">The <see cref="TimeSpan"/> to be formatted.</param>
+        /// <returns>A formatted string that can be displayed in the UI.</returns>
+        public static string FormatTimeSpan(TimeSpan? timeSpan)
+        {
+            if (!timeSpan.HasValue || timeSpan.Value.TotalSeconds < 1)
+            {
+                // Game was never played
+                return TimeSpan.Zero.ToString("c", CultureInfo.InvariantCulture);
+            }
+
+            if (timeSpan.Value.TotalDays < 1)
+            {
+                // Game was played for less than a day
+                return timeSpan.Value.ToString("c", CultureInfo.InvariantCulture);
+            }
+
+            // Game was played for more than a day
+            TimeSpan onlyTime = timeSpan.Value.Subtract(TimeSpan.FromDays(timeSpan.Value.Days));
+            string onlyTimeString = onlyTime.ToString("c", CultureInfo.InvariantCulture);
+
+            return $"{timeSpan.Value.Days}d, {onlyTimeString}";
+        }
+
+        /// <summary>
+        /// Creates a human-readable string from a <see cref="DateTime"/>.
+        /// </summary>
+        /// <param name="utcDateTime">The <see cref="DateTime"/> to be formatted. This is expected to be UTC-based.</param>
+        /// <param name="culture">The <see cref="CultureInfo"/> that's used in formatting. Defaults to <see cref="CultureInfo.CurrentCulture"/>.</param>
+        /// <returns>A formatted string that can be displayed in the UI.</returns>
+        public static string FormatDateTime(DateTime? utcDateTime, CultureInfo culture = null)
+        {
+            culture ??= CultureInfo.CurrentCulture;
+
+            if (!utcDateTime.HasValue)
+            {
+                // In the Avalonia UI, this is turned into a localized version of "Never" by LocalizedNeverConverter.
+                return "Never";
+            }
+
+            return utcDateTime.Value.ToLocalTime().ToString(culture);
+        }
+
+        /// <summary>
+        /// Creates a human-readable file size string.
+        /// </summary>
+        /// <param name="size">The file size in bytes.</param>
+        /// <param name="forceUnit">Formats the passed size value as this unit, bypassing the automatic unit choice.</param>
+        /// <returns>A human-readable file size string.</returns>
+        public static string FormatFileSize(long size, FileSizeUnits forceUnit = FileSizeUnits.Auto)
+        {
+            if (size <= 0)
+            {
+                return $"0 {_fileSizeUnitStrings[0]}";
+            }
+
+            int unitIndex = (int)forceUnit;
+            if (forceUnit == FileSizeUnits.Auto)
+            {
+                unitIndex = Convert.ToInt32(Math.Floor(Math.Log(size, SizeBase10)));
+
+                // Apply an upper bound so that exabytes are the biggest unit used when formatting.
+                if (unitIndex > UnitEBIndex)
+                {
+                    unitIndex = UnitEBIndex;
+                }
+            }
+
+            double sizeRounded;
+
+            if (unitIndex > UnitEBIndex)
+            {
+                sizeRounded = Math.Round(size / Math.Pow(SizeBase10, unitIndex - UnitEBIndex), 1);
+            }
+            else
+            {
+                sizeRounded = Math.Round(size / Math.Pow(SizeBase2, unitIndex), 1);
+            }
+
+            string sizeFormatted = sizeRounded.ToString(CultureInfo.InvariantCulture);
+
+            return $"{sizeFormatted} {_fileSizeUnitStrings[unitIndex]}";
+        }
+
+        #endregion
+
+        #region Value parsers
+
+        /// <summary>
+        /// Parses a string generated by <see cref="FormatTimeSpan"/> and returns the original <see cref="TimeSpan"/>.
+        /// </summary>
+        /// <param name="timeSpanString">A string representing a <see cref="TimeSpan"/>.</param>
+        /// <returns>A <see cref="TimeSpan"/> object. If the input string couldn't been parsed, <see cref="TimeSpan.Zero"/> is returned.</returns>
+        public static TimeSpan ParseTimeSpan(string timeSpanString)
+        {
+            TimeSpan returnTimeSpan = TimeSpan.Zero;
+
+            // An input string can either look like "01:23:45" or "1d, 01:23:45" if the timespan represents a duration of more than a day.
+            // Here, we split the input string to check if it's the former or the latter.
+            var valueSplit = timeSpanString.Split(", ");
+            if (valueSplit.Length > 1)
+            {
+                var dayPart = valueSplit[0].Split("d")[0];
+                if (int.TryParse(dayPart, out int days))
+                {
+                    returnTimeSpan = returnTimeSpan.Add(TimeSpan.FromDays(days));
+                }
+            }
+
+            if (TimeSpan.TryParse(valueSplit.Last(), out TimeSpan parsedTimeSpan))
+            {
+                returnTimeSpan = returnTimeSpan.Add(parsedTimeSpan);
+            }
+
+            return returnTimeSpan;
+        }
+
+        /// <summary>
+        /// Parses a string generated by <see cref="FormatDateTime"/> and returns the original <see cref="DateTime"/>.
+        /// </summary>
+        /// <param name="dateTimeString">The string representing a <see cref="DateTime"/>.</param>
+        /// <returns>A <see cref="DateTime"/> object. If the input string couldn't be parsed, <see cref="DateTime.UnixEpoch"/> is returned.</returns>
+        public static DateTime ParseDateTime(string dateTimeString)
+        {
+            if (!DateTime.TryParse(dateTimeString, CultureInfo.CurrentCulture, out DateTime parsedDateTime))
+            {
+                // Games that were never played are supposed to appear before the oldest played games in the list,
+                // so returning DateTime.UnixEpoch here makes sense.
+                return DateTime.UnixEpoch;
+            }
+
+            return parsedDateTime;
+        }
+
+        /// <summary>
+        /// Parses a string generated by <see cref="FormatFileSize"/> and returns a <see cref="long"/> representing a number of bytes.
+        /// </summary>
+        /// <param name="sizeString">A string representing a file size formatted with <see cref="FormatFileSize"/>.</param>
+        /// <returns>A <see cref="long"/> representing a number of bytes.</returns>
+        public static long ParseFileSize(string sizeString)
+        {
+            // Enumerating over the units backwards because otherwise, sizeString.EndsWith("B") would exit the loop in the first iteration.
+            for (int i = _fileSizeUnitStrings.Length - 1; i >= 0; i--)
+            {
+                string unit = _fileSizeUnitStrings[i];
+                if (!sizeString.EndsWith(unit))
+                {
+                    continue;
+                }
+
+                string numberString = sizeString.Split(" ")[0];
+                if (!double.TryParse(numberString, CultureInfo.InvariantCulture, out double number))
+                {
+                    break;
+                }
+
+                double sizeBase = SizeBase2;
+
+                // If the unit index is one that points to a base 10 unit in the FileSizeUnitStrings array, subtract 6 to arrive at a usable power value.
+                if (i > UnitEBIndex)
+                {
+                    i -= UnitEBIndex;
+                    sizeBase = SizeBase10;
+                }
+
+                number *= Math.Pow(sizeBase, i);
+
+                return Convert.ToInt64(number);
+            }
+
+            return 0;
+        }
+
+        #endregion
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs
new file mode 100644
index 00000000..7989f0f1
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Amiibo
+{
+    public struct AmiiboApi : IEquatable<AmiiboApi>
+    {
+        [JsonPropertyName("name")]
+        public string Name { get; set; }
+        [JsonPropertyName("head")]
+        public string Head { get; set; }
+        [JsonPropertyName("tail")]
+        public string Tail { get; set; }
+        [JsonPropertyName("image")]
+        public string Image { get; set; }
+        [JsonPropertyName("amiiboSeries")]
+        public string AmiiboSeries { get; set; }
+        [JsonPropertyName("character")]
+        public string Character { get; set; }
+        [JsonPropertyName("gameSeries")]
+        public string GameSeries { get; set; }
+        [JsonPropertyName("type")]
+        public string Type { get; set; }
+
+        [JsonPropertyName("release")]
+        public Dictionary<string, string> Release { get; set; }
+
+        [JsonPropertyName("gamesSwitch")]
+        public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
+
+        public readonly override string ToString()
+        {
+            return Name;
+        }
+
+        public readonly string GetId()
+        {
+            return Head + Tail;
+        }
+
+        public readonly bool Equals(AmiiboApi other)
+        {
+            return Head + Tail == other.Head + other.Tail;
+        }
+
+        public readonly override bool Equals(object obj)
+        {
+            return obj is AmiiboApi other && Equals(other);
+        }
+
+        public readonly override int GetHashCode()
+        {
+            return HashCode.Combine(Head, Tail);
+        }
+
+        public static bool operator ==(AmiiboApi left, AmiiboApi right)
+        {
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(AmiiboApi left, AmiiboApi right)
+        {
+            return !(left == right);
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
new file mode 100644
index 00000000..40e635bf
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Amiibo
+{
+    public class AmiiboApiGamesSwitch
+    {
+        [JsonPropertyName("amiiboUsage")]
+        public List<AmiiboApiUsage> AmiiboUsage { get; set; }
+        [JsonPropertyName("gameID")]
+        public List<string> GameId { get; set; }
+        [JsonPropertyName("gameName")]
+        public string GameName { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs
new file mode 100644
index 00000000..4f8d292b
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Amiibo
+{
+    public class AmiiboApiUsage
+    {
+        [JsonPropertyName("Usage")]
+        public string Usage { get; set; }
+        [JsonPropertyName("write")]
+        public bool Write { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs
new file mode 100644
index 00000000..15083f50
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Amiibo
+{
+    public struct AmiiboJson
+    {
+        [JsonPropertyName("amiibo")]
+        public List<AmiiboApi> Amiibo { get; set; }
+        [JsonPropertyName("lastUpdated")]
+        public DateTime LastUpdated { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
new file mode 100644
index 00000000..bc3f1303
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Amiibo
+{
+    [JsonSerializable(typeof(AmiiboJson))]
+    public partial class AmiiboJsonSerializerContext : JsonSerializerContext
+    {
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
new file mode 100644
index 00000000..8f528dc0
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.UI.Common.Models.Github
+{
+    public class GithubReleaseAssetJsonResponse
+    {
+        public string Name { get; set; }
+        public string State { get; set; }
+        public string BrowserDownloadUrl { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs
new file mode 100644
index 00000000..0250e109
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace Ryujinx.UI.Common.Models.Github
+{
+    public class GithubReleasesJsonResponse
+    {
+        public string Name { get; set; }
+        public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
new file mode 100644
index 00000000..71864257
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.UI.Common.Models.Github
+{
+    [JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
+    public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext
+    {
+    }
+}
diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg
new file mode 100644
index 00000000..03585e65
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st1{fill:#02c5e5}</style><style id="style2-6" type="text/css">.st1{fill:#02c5e5}.st3{fill:#fff}</style><g id="g344" transform="translate(0,300)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="225.8 469.9 250 469.9 237.9 448.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="237.9 626.9 225.8 605.9 250 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="148.9 537.9 169.9 550 169.9 525.8" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="305.9 550 305.9 525.8 326.9 537.9" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="m 388.84323,464.93186 0.0252,-5.22079 0.35628,-387.023108 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/></g><ellipse id="path4030" cx="-630.031" cy="861.013" rx="15.407" ry="14.105" transform="scale(-1,1)" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4038" d="m 531.57205,538.85036 v 45.92786" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4040" d="M 538.66113,544.78398 V 581.251" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4062" d="m 618.21618,561.30922 c 0.15897,-2.39247 0.93393,-4.19426 2.34943,-5.4612 1.05382,-0.94329 2.4969,-1.60711 4.18689,-1.92587 0.38638,-0.0728 1.08711,-0.17756 1.09745,-0.16356 0,0.005 0.0932,0.85525 0.2017,1.89259 0.10822,1.03731 0.20533,1.93952 0.21568,2.00495 0.0181,0.10453 0.0103,0.11877 -0.0516,0.11877 -0.12143,0 -0.66218,0.12325 -1.06042,0.24145 -1.89486,0.56317 -2.9076,1.70318 -3.13568,3.52943 -0.0526,0.41968 0.2402,1.20332 0.3147,1.59414 0.19574,1.0321 0.5477,1.44923 1.24585,1.96064 0.54534,0.39941 0.84078,0.63241 1.52991,0.63397 0.49114,0 0.79513,-0.17703 1.12084,-0.34918 0.22397,-0.11875 0.54525,-0.72408 0.72476,-0.97125 0.4284,-0.59002 0.57331,-0.18167 1.33421,-2.91459 0.47521,-1.70735 0.75977,-2.52129 1.19088,-3.4071 0.58401,-1.19961 1.35632,-2.06979 2.41398,-2.71969 0.58281,-0.35813 1.33375,-0.64229 2.04739,-0.77469 0.33923,-0.0633 0.49023,-0.0718 1.18512,-0.0711 0.6888,7.5e-4 0.84197,0.01 1.1342,0.0705 1.71036,0.34984 3.14515,1.32777 3.98586,2.71644 0.37788,0.62406 0.6928,1.43192 0.8702,2.23216 0.38944,1.75661 0.31125,4.08353 -0.19239,5.72547 -0.23225,0.75754 -0.63066,1.547 -1.06364,2.10803 -0.29761,0.38576 -1.03764,1.06284 -1.46261,1.33836 -0.68025,0.44086 -1.27214,1.08216 -2.11357,1.24388 -0.42538,0.0817 -1.27033,-0.14168 -1.5376,-0.14168 h -0.15716 l -2.2e-4,-0.18229 c -1.6e-4,-0.10006 -0.0391,-0.97392 -0.0865,-1.94151 -0.0477,-0.9676 -0.0862,-1.8095 -0.0862,-1.87098 l -7e-5,-0.11166 0.30292,-0.0566 c 0.67911,-0.12659 0.64274,-0.69151 1.05495,-1.00838 0.80274,-0.61701 1.57932,-1.59904 1.57884,-3.10599 -2.4e-4,-0.99245 -0.26656,-1.2378 -0.6209,-1.90047 -0.41109,-0.7689 -0.52472,-0.63395 -1.25089,-0.66875 -0.54033,-0.0264 -0.60261,0.54818 -0.97987,0.86389 -0.60357,0.50503 -0.65515,0.26871 -1.33681,2.74768 -0.53065,1.92992 -1.61672,3.72692 -2.02402,4.67676 -0.7236,1.68735 -1.46229,1.88688 -2.90464,2.54118 -0.86271,0.39132 -1.65737,0.56338 -2.80448,0.60727 -1.3619,0.0524 -2.61283,-0.24592 -3.80829,-0.90695 -1.3364,-0.73899 -2.29253,-1.88343 -2.83806,-3.39691 -0.47562,-1.31947 -0.68418,-3.07542 -0.56986,-4.79727 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4064" d="m 630.09646,971.66625 h 11.20079 l -7.7e-4,4.47736 c -3.9e-4,2.46263 -0.0181,4.8542 -0.0344,5.31477 -0.12014,3.00951 -0.56807,4.32259 -1.86223,5.4598 -1.43936,1.26481 -3.65136,1.78958 -5.84831,1.38753 -1.22398,-0.224 -2.30114,-0.78622 -3.1233,-1.63027 -0.75525,-0.77541 -1.34589,-2.02193 -1.58341,-3.3415 -0.0526,-0.2928 -0.0649,-0.32336 -0.10591,-0.26949 -0.0258,0.0337 -0.20067,0.27472 -0.38963,0.53623 -0.79262,1.09807 -1.46856,1.72397 -2.8174,2.60895 -0.78277,0.51353 -1.17221,0.74339 -4.12365,2.43453 l -2.49548,1.4299 -0.008,-2.44288 c -0.005,-1.92858 2.7e-4,-2.45065 0.0344,-2.47945 0.0234,-0.0215 1.34449,-0.8352 2.93457,-1.81113 4.5931,-2.81923 5.11319,-3.17081 5.65776,-3.8248 0.54019,-0.64863 0.67406,-1.16979 0.70337,-2.7382 l 0.0181,-0.99053 h -4.67857 -4.67867 v -2.06046 -2.06036 h 11.20079 z m 1.74946,9.28763 c 0.0409,0.67298 0.11392,1.26781 0.18719,1.52499 0.22165,0.77651 0.88153,1.38438 1.75173,1.61386 0.32467,0.0855 1.148,0.12136 1.50829,0.0653 0.87376,-0.13534 1.48211,-0.5375 1.85019,-1.22332 0.35302,-0.65774 0.37769,-0.95998 0.37905,-4.65174 l 7.5e-4,-2.49624 h -2.85643 -2.85653 l 7e-5,2.29025 c 0,1.25954 0.0181,2.55403 0.0356,2.87661 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4066" d="m 618.48834,960.72379 c 0.26992,-3.13481 1.47063,-5.14907 3.82731,-6.42085 0.94544,-0.51008 2.47246,-0.96116 3.66673,-1.08314 l 0.21439,-0.0214 0.0207,0.10785 c 0.0372,0.19794 0.41957,3.90855 0.40445,3.92234 -0.008,0.007 -0.17193,0.0441 -0.3639,0.0822 -0.19212,0.0376 -0.53821,0.12634 -0.76937,0.19651 -1.79072,0.54475 -2.7801,1.57117 -3.10355,3.21988 -0.0989,0.50413 -0.10744,1.60822 -0.0155,2.14051 0.12169,0.71048 0.32194,1.25035 0.6218,1.6747 0.41144,0.58234 0.98794,1.0195 1.60624,1.21829 0.34978,0.11236 1.05168,0.14484 1.3996,0.0645 0.68302,-0.15762 1.12961,-0.53488 1.53764,-1.29896 0.28622,-0.53585 0.48608,-1.14697 1.12493,-3.44026 0.58179,-2.0886 0.89522,-2.93441 1.4688,-3.96444 0.54763,-0.9834 1.29532,-1.75609 2.25091,-2.32632 1.0162,-0.60643 2.16997,-0.88864 3.44103,-0.84174 1.09522,0.0405 2.1108,0.34696 3.03462,0.9161 0.67952,0.41875 1.15791,0.85897 1.62314,1.49397 0.94821,1.29426 1.41875,3.00624 1.41828,5.1604 -5.4e-4,2.4013 -0.5283,4.2219 -1.61346,5.56569 -0.28052,0.34751 -0.87705,0.89358 -1.25657,1.15047 -1.02517,0.69385 -2.17752,1.07827 -3.55571,1.18615 -0.21154,0.0168 -0.38907,0.0262 -0.39448,0.0215 -0.0155,-0.0141 -0.21309,-4.13646 -0.20041,-4.14922 0.008,-0.007 0.14966,-0.0386 0.32003,-0.0726 0.96084,-0.19177 1.73387,-0.57719 2.16612,-1.08024 0.33457,-0.38922 0.56064,-0.89429 0.68786,-1.53658 0.1015,-0.51332 0.11134,-1.67163 0.0181,-2.21419 -0.14526,-0.84985 -0.46593,-1.54361 -0.92193,-1.99457 -0.48336,-0.47793 -1.31478,-0.61609 -1.9837,-0.32951 -0.30417,0.13037 -0.66295,0.44566 -0.87729,0.7711 -0.39693,0.60258 -0.7762,1.64298 -1.28809,3.53321 -0.61793,2.28163 -1.08691,3.57856 -1.64611,4.55253 -0.90497,1.57616 -2.40653,2.63296 -4.21401,2.96573 -0.65494,0.12066 -1.14141,0.15526 -1.88939,0.13511 -0.52546,-0.0141 -0.75937,-0.0355 -1.08943,-0.0994 -1.82284,-0.35238 -3.39382,-1.33729 -4.32844,-2.71383 -0.65796,-0.969 -1.07881,-2.20396 -1.27779,-3.74995 -0.0534,-0.41339 -0.0974,-2.3393 -0.0626,-2.74128 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4068" d="m 630.08177,575.12806 11.69573,-0.0768 0.11296,2.83872 -0.11296,2.7832 -10.22217,-0.0657 -8.46941,0.0657 -0.23931,4.64789 -0.21033,5.23455 -2.19525,-0.11373 h -1.89113 v -7.29401 l -0.13688,-8.09662 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path249" d="m 564.81854,320.07351 2.80254,-2.94783 2.10843,-1.80063 3.89781,-2.62722 4.93974,-2.563 3.81131,-1.26428 3.8729,-0.82566 1.38974,-0.20307 2.88842,-0.16699 h 57.79227 l 1.57144,0.1495 1.7697,0.23946 1.77484,0.23845 2.72964,0.54365 2.31281,0.60657 2.44326,0.75609 2.94394,0.94407 2.12886,0.90455 3.8498,1.71936 2.75741,1.53909 2.10581,1.19691 3.23498,2.16487 2.4201,1.63817 1.43595,1.20589 1.89607,1.45278 3.21175,2.60881 2.42278,2.54722 4.25902,4.70095 2.59949,3.25688 1.67743,2.63026 1.27103,2.18885 1.91183,3.73696 0.72706,1.65104 1.16131,2.96921 0.66224,2.6045 0.78479,3.27949 0.33987,2.68699 0.0483,2.38913 v 4.00596 2.85158 877.28853 l -0.16384,2.4984 -0.34524,3.4016 -1.29885,4.7808 -1.23966,3.7841 -3.60497,7.2728 -2.57375,4.0663 -2.46855,3.2069 -1.48186,1.9802 -2.66944,2.87 -3.06989,3.0298 -2.17649,1.9303 -4.01872,3.1261 -4.11447,2.8611 -2.30753,1.2764 -3.52352,1.8502 -3.6903,1.6841 -4.15406,1.4576 -3.72593,1.1705 -3.68244,0.746 -3.28501,0.4427 -3.07889,0.2681 h -56.72802 l -2.27377,-0.2166 -3.66214,-0.647 -2.13716,-0.5101 -2.60358,-0.9022 -3.70761,-1.5158 -3.72085,-1.8958 -3.11883,-1.9649 -2.49439,-2.0644 -3.08564,-2.8864 -3.11412,-3.839 -2.38795,-3.9255 -1.37928,-3.2422 -1.06978,-2.9089 -0.81446,-3.3604 -0.4154,-3.6114 -0.024,-2.148 V 343.23256 l 0.28062,-2.94096 0.63887,-3.85473 1.31769,-4.26752 1.53215,-3.69272 2.5337,-4.4686 1.96993,-2.5833 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path253" d="m 694.62149,334.10362 2.87464,2.17056 1.39448,1.27449 1.10633,1.19174 1.33926,1.50114 1.38209,1.74045 1.13752,1.55135 1.14707,1.6191 1.76331,2.78539 1.13353,1.9937 0.91903,1.69462 1.33241,2.59815 1.11209,2.33 1.56583,3.39111 0.63568,1.22029 0.77282,1.85718 0.72486,1.75471 0.98903,2.11635 1.04466,2.26736 0.86003,1.7056 0.74871,1.46183 0.77843,1.50459 1.16158,2.03635 0.69941,1.16948 1.32156,2.11591 1.16136,1.5888 0.91829,1.1277 1.46722,1.69949 1.41993,1.42143 1.99344,1.72936 2.2557,1.72741 2.15114,1.20765 1.3718,0.68691 3.115,1.23393 4.1538,1.06385 3.08686,0.4687 3.22131,0.30291 h 28.48289 l 0.94647,0.0524 0.97841,0.35799 1.16352,0.47513 0.9822,0.70154 1.01456,1.07822 0.92826,1.35838 0.65022,1.72693 0.1277,1.59566 -0.29606,1.44502 -0.74147,1.59474 -1.99052,3.45657 -2.4225,4.16279 -2.33536,3.53915 -1.37414,1.9664 -1.24262,1.70801 -1.41326,1.83088 -1.34109,1.74508 -2.14664,2.66591 -1.97231,2.31029 -1.08591,1.37517 -2.41419,2.77055 -1.30886,1.52879 -3.03361,3.40228 -1.58159,1.80779 -1.34438,1.31431 -2.46317,2.6295 -1.04614,1.0908 -4.84623,5.03258 -3.60112,3.77568 -1.74314,1.82893 -2.10543,2.2459 -6.06161,6.49298 -2.39368,2.59389 -2.01406,2.20329 -1.6282,1.85603 -1.14047,1.25547 -1.6465,1.98517 -1.72596,2.18615 -1.52881,1.91959 -1.25534,1.48184 -1.12938,1.52402 -1.65189,2.2517 -1.15137,1.60225 -1.31306,1.81213 -1.08907,1.73832 -1.86192,2.96443 -1.97162,3.32339 -1.21492,2.47246 -1.36959,2.68936 -0.95325,2.42774 -1.07073,2.91455 -0.76263,2.02052 h -0.62464"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path255" d="m 554.98557,806.60461 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97257 -0.93192,0.98281 -0.8244,1.30431 -0.46075,1.2916 -0.0637,0.91287 -0.15809,2.36292 -0.25772,3.06459 -0.2171,3.23629 -0.2039,3.99231 -0.12562,3.06084 -0.14526,4.35384 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37395 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.13471 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path298" d="m 554.91046,880.77518 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path300" d="m 555.35214,1000.9073 -0.70664,0.01 -1.15041,0.3129 -0.94439,0.9042 -0.33283,0.8403 v 55.3836 l 0.35102,0.988 1.16661,1.0639 0.76614,0.2105 0.79763,-0.043 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path302" d="m 683.4822,322.5276 1.80756,-0.36865 3.52048,0.79736 3.29989,0.79341 3.35684,0.85712 10.58481,3.05757 8.24268,2.61795 6.98289,2.30801 8.19137,2.72032 6.85494,2.1232 7.56186,2.22326 3.02344,0.89258 3.01485,0.78292 2.59184,0.6545 4.39682,1.01106 3.44978,0.73216 4.14889,0.73189 5.67397,0.74901 2.26019,0.25821 2.51619,0.19404 1.51308,0.53857 1.71443,0.82574 1.15366,0.80631 0.81926,0.61787 1.09348,1.17223 1.28918,1.66295 1.03628,2.03633 0.40058,1.60306 0.18894,1.03784 v 22.44381 l -0.19091,1.309 -0.49575,1.41249 -0.82966,1.654 -0.83314,1.22068 -1.26559,1.52171 -1.47306,1.67951 -1.74719,1.81065 -1.52584,1.67117 -1.0269,1.42993 -0.51569,0.92494"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path304" d="m 555.11995,518.09615 -1.01033,0.39258 -1.22841,0.93655 -1.2742,1.02924 -1.33354,1.35102 -1.34981,1.59351 -1.40742,1.80058 -1.06793,1.49244 -0.85098,1.20282 -0.89272,1.39504 -0.99731,1.62995 -0.60208,1.24653 -0.8025,1.69239 -0.93246,1.96822 -0.91473,2.23059 -0.62621,1.91229 -0.57345,2.01006 -0.59474,2.80402 -0.14894,0.35985 -1.18136,-0.13793 -0.97443,-0.18501 -1.29147,-0.54083 -1.00174,-0.69084 -1.15445,-0.99791 -0.60398,-0.85223 -0.49335,-1.12318 -0.37025,-1.37685 v -45.45096 l -0.20339,-1.17956 -0.74794,-1.09777 -0.87864,-0.84867 -1.1084,-0.66091 -1.62768,-0.61457 -1.99954,-0.31262 -2.41898,-0.0433 -3.34195,0.51108 -2.789,1.02869 -1.75751,0.92812 -1.48061,0.99716 -2.10544,1.93079 -1.35698,1.79438 -0.77464,1.80822 -0.53822,2.14889 -0.17548,1.82929 v 15.40503 l -0.74254,2.33437 -0.81509,3.04978 -0.66374,2.10772 -1.44608,5.41074 -0.10817,0.54556 -0.36239,1.62223 -0.43835,2.01252 -0.52816,2.59666 -0.51106,2.94424 -0.53199,3.41725 -0.52183,3.69125 -0.27377,2.56523 -0.17416,1.97814 -0.12505,1.76866 -0.16865,2.53094 -0.0926,2.51807 -0.10085,2.96479 -0.0322,3.59841 0.1372,3.62771 0.15883,3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path306" d="m 555.11995,607.38224 -1.01033,-0.39258 -1.22841,-0.93654 -1.2742,-1.02925 -1.33354,-1.35102 -1.34981,-1.5935 -1.40742,-1.80059 -1.06793,-1.49243 -0.85098,-1.20282 -0.89272,-1.39505 -0.99731,-1.62995 -0.60208,-1.24653 -0.8025,-1.69239 -0.93246,-1.96821 -0.91473,-2.23059 -0.62621,-1.9123 -0.57345,-2.01006 -0.59474,-2.80402 -0.14894,-0.35985 -1.18136,0.13793 -0.97443,0.18501 -1.29147,0.54083 -1.00174,0.69084 -1.15445,0.99792 -0.60398,0.85223 -0.49335,1.12317 -0.37025,1.37685 v 45.45097 l -0.20339,1.17956 -0.74794,1.09777 -0.87864,0.84866 -1.1084,0.66092 -1.62768,0.61456 -1.99954,0.31262 -2.41898,0.0433 -3.34195,-0.51107 -2.789,-1.0287 -1.75751,-0.92812 -1.48061,-0.99715 -2.10544,-1.93079 -1.35698,-1.79438 -0.77464,-1.80823 -0.53822,-2.14889 -0.17548,-1.82929 v -15.40503 l -0.74254,-2.33437 -0.81509,-3.04977 -0.66374,-2.10773 -1.44608,-5.41074 -0.10817,-0.54555 -0.36239,-1.62224 -0.43835,-2.01252 -0.52816,-2.59665 -0.51106,-2.94425 -0.53199,-3.41725 -0.52183,-3.69125 -0.27377,-2.56522 -0.17416,-1.97815 -0.12505,-1.76866 -0.16865,-2.53094 -0.0926,-2.51807 -0.10085,-2.96479 -0.0322,-3.5984 0.1372,-3.62772 0.15883,-3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path310" d="m 629.00102,930.67137 h 6.14653 l 2.04067,0.16215 1.12524,0.1958 1.57485,0.44983 1.37911,0.54025 1.49645,0.7516 1.16369,0.77595 1.20645,0.95903 1.07493,1.06679 1.10141,1.41857 0.59407,1.15018 0.53577,1.29561 0.50772,1.37166 0.10921,1.53404 0.0194,1.06304 v 58.84883 l -0.13659,1.1193 -0.20644,0.9935 -0.32745,0.917 -0.29571,0.8905 -0.50231,0.9886 -0.70348,1.073 -0.72708,0.8329 -1.14245,1.2323 -0.95483,0.8506 -1.12308,0.74 -1.3029,0.7638 -1.57811,0.6202 -1.75304,0.421 -1.62477,0.2527 -1.92906,0.036 h -12.21387 l -1.24442,-0.1438 -1.4416,-0.2655 -1.20902,-0.3547 -1.34067,-0.5911 -1.25475,-0.6462 -0.90721,-0.5402 -1.03832,-0.822 -0.71078,-0.7398 -0.67126,-0.637 -1.26722,-1.7893 -1.08212,-2.3971 -0.42262,-1.7353 -0.0315,-1.7747 v -59.09121 l 0.14146,-0.91134 0.21007,-0.66319 0.29836,-1.07418 0.44186,-1.07962 0.47325,-1.02037 0.3698,-0.61649 0.99623,-1.3542 0.95716,-1.00285 0.94225,-0.85279 0.88252,-0.60543 1.18795,-0.67902 1.33894,-0.6658 0.87252,-0.36273 0.97938,-0.32262 0.90474,-0.18457 1.43288,-0.23808 0.46681,-0.0584 1.01236,-0.055 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path320" d="m 705.29946,404.37113 h 4.94953 l 1.01129,0.19824 1.02198,0.65847 0.7694,0.84434 0.62305,1.2788 0.41165,1.37503 0.60375,2.17711 0.53032,2.14857 0.38266,1.97177 0.31418,1.95565 0.25283,2.01634 0.22113,2.18648 0.14186,2.361 0.0464,2.06343 -0.0339,2.90094 -0.18666,2.93049 -0.2597,3.12611 -0.3257,2.7483 -0.47254,2.43606 -0.38375,2.06954 -0.62275,2.43127 -0.48757,1.70574 -0.56732,1.13614 -0.65604,0.75733 -0.78933,0.54765 -0.77997,0.31884 -0.82705,0.0912 h -5.1673 -0.22961 V 404.3608 Z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path322" d="m 555.36415,396.79743 h -3.36229 l -0.95244,0.2579 -0.88685,0.75198 -0.3797,1.096 v 10.8053 l 0.39974,1.00083 0.47383,0.71418 0.63631,0.44263 0.50741,0.16001 h 3.36617 0.21167 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path324" d="m 606.45914,1054.8828 h 46.6816 l -23.3408,37.0116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path326" d="m 606.45914,1099.1543 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path328" d="m 606.45914,1143.4531 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path330" d="m 631.08566,1044.0909 h 27.01297 l 1.86984,0.2805 1.34197,0.3596 1.60607,0.6644 1.16604,0.7523 1.14122,0.8781 0.78333,0.8256 0.70342,0.7968 0.63184,1.1132 0.47977,0.9893 0.34526,1.0282 0.24865,1.1979 0.0693,0.8321 v 125.4568 l -0.0521,0.8725 -0.16665,1.0509 -0.4222,1.198 -0.73285,1.4957 -0.85365,1.1513 -1.41766,1.3555 -1.17786,0.9192 -1.59645,0.8597 -1.9127,0.616 -1.74431,0.1955 h -57.29204 l -1.482,-0.1172 -1.53793,-0.38 -1.02579,-0.42 -1.04703,-0.5563 -0.79838,-0.4864 -1.0868,-0.8174 -1.17978,-1.2797 -0.68706,-0.9209 -0.43671,-0.7767 -0.39717,-0.767 -0.36431,-1.0377 -0.17137,-0.7968 -0.0855,-1.2218 v -125.4649 l 0.0755,-1.1013 0.20402,-0.9527 0.22661,-0.7999 0.34294,-0.7651 0.79684,-1.4733 0.86432,-1.1445 1.36362,-1.2251 1.4025,-0.9497 0.76822,-0.4027 1.66903,-0.5936 1.31204,-0.2503 1.48443,-0.1826 1.15796,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path332" d="m 584.21811,307.65169 v -3.15652 l 0.37148,-1.45881 0.75589,-1.0701 1.18763,-0.98136 1.7025,-0.4849 h 45.22792 l 1.58355,0.18907 1.21322,0.58954 0.86017,0.63523 0.62083,0.6164 0.7767,1.22224 0.27256,1.40251 v 2.49159 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path334" d="m 554.98557,732.43405 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.1854 0.30831,1.25066 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path460" d="m 575.40725,1292.5752 c -8.50513,-4.4396 -14.59302,-11.4224 -17.41944,-18.9224 -0.26068,-0.6918 -2.10217,-5.5985 -2.32407,-16.4555 -0.95755,-46.8522 0.0692,-191.628 0.0924,-454.79146 0.0395,-447.17165 -1.16464,-463.77985 2.13444,-471.06146 4.14474,-9.14813 14.82174,-19.11565 24.20501,-21.93419 4.35355,-1.30772 20.60861,-0.88744 41.2504,-0.85913 9.13704,0.0125 16.72265,-0.38909 22.30143,-0.24437 9.7504,0.25294 14.61876,1.40481 19.8754,3.83273 13.20934,6.10107 27.37811,16.4207 32.31917,28.24068 1.2204,2.91943 4.50669,7.46836 6.1373,11.04497 l 1.41675,449.7216 -1.5273,449.96593 -4.08634,10.2294 c -5.14691,12.8843 -20.61785,27.6214 -33.70017,32.5287 -8.98936,3.372 -15.168,3.8603 -44.99389,3.8243 -13.98709,-0.017 -20.27955,0.078 -25.76681,0.1196 -1.4993,0.012 -2.53237,0.1219 -3.63781,0.1486 -1.8856,0.045 -3.47223,-0.1698 -5.13087,-0.6073 -1.2319,-0.3249 -1.88857,-0.4449 -3.07941,-0.9415 -0.66852,-0.2788 -1.67524,-0.6042 -2.54621,-0.9578 z m 96.94271,-95.8531 c 0.34361,-0.068 1.16774,-0.4225 1.45971,-0.6578 1.57938,-1.2724 3.13254,-2.332 3.76998,-3.2892 0.7553,-1.134 1.14301,-187.0038 1.15874,-414.46917 l -0.57612,-411.57378 -4.84312,-3.50599 c -3.43566,-2.48711 -8.52491,-1.47394 -44.87908,-1.47394 -41.01713,0 -42.12736,-0.69464 -45.65154,2.83862 -1.56374,1.56777 -1.68966,2.84556 -1.76015,34.2526 -0.0453,20.16919 -0.25443,52.7638 -0.18971,105.84008 0.042,34.48838 -0.39971,77.46436 -0.36851,131.48656 0.0237,40.99241 -0.34276,87.99166 -0.34276,142.48967 0,287.55485 0.28324,410.83535 1.67493,413.44235 1.09524,2.0518 3.44174,3.3319 5.68762,4.2392 3.12702,1.2631 22.75157,1.4763 43.15146,1.4245 20.73025,-0.053 38.09531,-0.3244 38.91512,-0.4876 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path462" d="m 518.18635,634.34636 c -2.0133,-0.74316 -4.7444,-2.43786 -6.06913,-3.766 -2.24227,-2.24804 -2.45006,-3.20634 -3.00903,-13.87724 -0.37592,-7.17651 -1.34402,-14.09008 -2.5891,-18.48986 -4.49032,-15.86754 -5.9821,-36.98433 -3.75165,-53.1062 0.55771,-4.0312 2.23996,-12.10143 3.73832,-17.93387 2.04085,-7.94409 2.72517,-12.76287 2.72779,-19.20823 0.003,-6.76442 0.37876,-9.22079 1.75882,-11.48976 3.34452,-5.49877 13.94314,-8.16727 17.96065,-4.52211 1.70953,1.55109 1.77236,4.0545 1.77236,70.62081 0,53.82758 -0.25772,69.36608 -1.17129,70.61868 -1.62169,2.2235 -6.99289,2.76866 -11.36774,1.15378 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path466" d="m 532.33814,562.77279 v -19.58771 l 0.74345,0.53648 c 1.46593,1.05782 3.20996,1.86326 4.03453,1.86326 h 0.83922 v 17.02133 17.02133 l -1.42098,0.35872 c -0.78154,0.19731 -2.04541,0.81224 -2.8086,1.36651 l -1.38762,1.00777 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path468" d="m 552.92579,605.12795 c -4.61024,-3.77319 -9.57996,-11.63826 -12.26532,-19.41107 l -1.21822,-3.52618 -0.0956,-18.65027 -0.0956,-18.65026 0.82611,-3.11181 c 2.00396,-7.54852 7.57379,-16.9297 12.61547,-21.24804 0.99001,-0.84797 1.87129,-1.47031 1.9584,-1.38298 0.0871,0.0873 0.12066,19.78469 0.0746,43.7719 l -0.0838,43.61311 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path470" d="m 554.24531,1059.9811 c -0.38562,-0.075 -1.29674,-1.1158 -1.37849,-1.5742 -0.0387,-0.2167 -0.0553,-12.8432 -0.037,-28.0588 l 0.0333,-27.6647 0.4632,-0.4756 c 0.38607,-0.3964 1.36731,-0.5813 1.75961,-0.5842 0.0482,-4e-4 -0.29526,13.0536 -0.29526,29.1581 0,23.3551 -0.0295,29.2776 -0.14603,29.2649 -0.0803,-0.01 -0.26001,-0.038 -0.39932,-0.065 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path472" d="m 620.42769,1013.2884 c -3.57448,-0.8725 -8.96012,-1.3788 -9.30569,-4.7082 l -0.67815,-2.0055 -0.25138,-4.2445 0.41829,-28.18567 c 0.29654,-19.98156 0.0411,-31.19328 0.50411,-32.91713 0.89622,-3.33689 2.97585,-6.44453 6.44362,-8.30431 2.42416,-1.3001 4.38417,-2.04911 12.31933,-2.04911 7.87316,0 9.30668,0.50275 11.63947,1.76142 3.17156,1.71124 4.95339,4.25793 5.90801,6.78394 1.14299,3.02444 0.95659,63.49706 -0.2043,66.28266 -1.21207,2.9084 -4.61574,6.4491 -8.13563,7.3377 -1.79168,0.4523 -6.47414,0.5577 -10.75587,0.4249 -3.25525,-0.101 -6.55619,0.1522 -7.90181,-0.1762 z m 0.80576,-24.14851 c 1.16322,-0.59784 3.35864,-1.93991 4.87872,-2.98238 2.69355,-1.84722 2.34692,-3.71595 2.76767,-2.38687 0.63441,2.00401 4.72774,5.3999 7.58335,4.8628 4.05952,-0.76353 5.0585,-2.82168 5.0585,-10.42179 v -6.53615 h -11.56483 l -11.51834,-0.0293 -4.7e-4,2.21816 0.0337,2.30803 4.63541,-0.0188 c 2.73527,-0.0111 4.24552,-0.44405 4.73547,-0.17155 0.39185,0.21794 0.0185,1.05358 -0.0712,1.68697 -0.14172,1.00046 -0.53695,2.34895 -3.53063,4.29524 -4.24127,2.7574 -5.67341,3.26403 -5.67341,5.70376 0,2.93489 -0.17135,2.93009 2.66607,1.47192 z m 8.72451,-20.28022 c 0.99255,-0.85681 2.35557,-3.3221 3.20525,-5.79732 1.14206,-3.32696 1.57736,-4.85966 2.57572,-4.85966 1.01595,0 1.82378,0.89997 1.98484,2.8501 0.17554,2.12547 -0.11777,2.73658 -1.58921,3.40873 -1.04809,0.47877 -1.79454,1.18693 -1.5773,1.75451 0.19578,0.5115 0.35596,1.50192 0.35596,2.20091 0,2.45771 4.7924,0.83849 6.32761,-2.13792 1.93784,-3.75702 0.66824,-10.20362 -2.32592,-11.81016 -2.08149,-1.11685 -5.66885,-0.79036 -7.54137,0.68637 -1.06893,0.84298 -1.92531,2.93981 -2.5499,5.09386 -1.30345,4.49527 -2.63948,5.88742 -4.17433,5.29693 -2.96077,-1.13908 -2.57455,-6.88848 0.56458,-7.67838 1.60085,-0.40282 2.28581,-2.23765 1.18075,-3.98616 -0.8873,-1.40395 -4.41318,-0.29463 -6.33262,1.99237 -1.36577,1.62731 -1.66572,2.67452 -1.64657,5.7486 0.0129,2.06736 0.41734,4.47138 0.8988,5.34228 1.94785,3.52339 7.593,4.52842 10.64371,1.89494 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00c8e8;fill-opacity:.992157;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path474" d="m 632.81036,983.17958 c -0.63556,-0.67826 -0.71845,-1.13691 -0.71845,-3.9753 v -3.20858 h 2.64339 2.64339 v 3.10243 c 0,2.63704 -0.10273,3.23338 -0.68483,3.97531 -0.91474,1.16589 -2.84114,1.21855 -3.8835,0.10614 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path476" d="m 614.90041,611.55893 c -5.47818,-3.70126 -5.46194,-5.62841 -5.47319,-39.94991 -0.01,-29.83751 0.23875,-32.42084 2.03054,-35.3673 2.73782,-4.50213 9.7432,-6.34849 18.29821,-6.34849 8.55502,0 14.93848,1.49439 17.6763,5.99652 1.78955,2.94276 1.41474,6.84185 1.41806,36.21097 0.003,28.17503 0.0839,31.98162 -1.47142,34.88922 -2.76995,5.17816 -6.88103,7.15268 -17.83149,7.15268 -8.29531,0 -11.8731,-0.70953 -14.64701,-2.58369 z m 8.18551,-25.73237 v -5.15343 h 9.34579 9.34579 v -2.81096 -2.81096 h -11.68224 -11.68224 v 7.96439 c 0,7.87069 -0.17512,7.83539 2.13383,7.83539 2.209,0 2.53907,-0.1521 2.53907,-5.02443 z m 7.19177,-16.60471 c 0.18831,-0.0366 0.45055,-0.54459 0.6657,-0.86103 0.6596,-0.97009 1.35497,-2.74044 1.9953,-4.67326 1.56982,-4.73845 3.62862,-5.98608 4.17546,-2.25932 0.17631,1.20159 -0.48112,2.61937 -1.34586,2.95206 -1.97767,0.76085 -1.99781,5.98598 -0.0231,5.98598 2.81061,0 6.03228,-4.36968 6.03228,-8.18181 0,-2.26738 -0.66708,-3.89433 -1.4774,-5.16066 -1.05092,-1.64231 -2.52443,-2.58631 -4.9728,-2.58631 -4.07241,0 -5.67625,1.85418 -7.32959,7.01759 -1.35947,4.24563 -2.76574,4.90543 -4.63024,3.03612 -1.76893,-1.77348 -2.21107,-4.65285 0.27445,-5.44376 1.94089,-0.6176 3.84262,-4.09021 2.19133,-5.11339 -0.54505,-0.33773 -2.20902,-0.10822 -3.69771,0.51 -2.80301,1.16403 -4.21198,4.73237 -4.21865,8.18117 -0.005,2.38104 0.56756,4.70512 2.18461,6.14168 2.68538,2.38566 6.4958,1.17087 9.91016,0.5067 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path480" d="m 583.49685,1194.3213 c -2.63205,-2.6388 -2.64339,-4.417 -2.64339,-414.70449 l 0.91025,-380.56509 0.0768,-32.0953 2.17287,-2.77511 c 2.35098,-3.00257 4.18121,-2.02246 45.18478,-2.02246 39.9348,0 42.75186,0.15622 45.67967,2.53317 l 2.95718,2.71194 0.16306,412.16132 -0.67534,412.51752 -2.4449,2.3556 c -2.71646,2.6173 -5.74931,2.5331 -45.92889,2.5331 -41.04641,0 -42.91748,-0.1091 -45.45206,-2.6502 z m 81.84368,-7.4058 3.14423,-4.037 0.0827,-66.2535 -0.39676,-66.5434 -2.26148,-3.3325 -3.88235,-2.7418 -32.27071,-0.7473 -32.79612,1.1063 -3.61057,2.1462 -3.24416,3.2525 v 66.7245 c 0,51.3889 0.37971,67.2017 1.65212,68.8007 3.62406,4.5542 6.83181,4.9751 38.22774,5.0155 l 30.77046,-0.8736 z m -24.61354,-173.581 c 7.9414,-2.7755 8.14807,-3.0866 8.14807,-41.16306 0,-32.95752 -0.10203,-35.06928 -2.67771,-37.65159 -1.48289,-1.48673 -4.16023,-2.90576 -5.99586,-3.60546 -4.95757,-1.88972 -17.0157,-1.44776 -22.15047,0.7032 -8.08162,3.38542 -8.9198,5.00242 -8.9198,40.79416 0,20.04755 0.002,33.57605 0.88389,35.22855 2.69585,5.0502 9.31002,6.769 18.65804,6.7743 4.79831,0 9.81254,-0.2968 12.05384,-1.0801 z m -1.58398,-140.068 c 5.13925,-3.46846 7.09546,-8.3228 6.85914,-13.07417 -0.16881,-3.39392 -1.37155,-6.53272 -4.41417,-9.45525 -6.97318,-6.69795 -19.07399,-5.59067 -24.94988,1.89858 -3.21578,4.09873 -3.22084,12.29018 -0.22077,16.5844 4.76762,6.82428 15.50209,8.92162 22.72568,4.04644 z m -1.36978,-61.94554 c 2.03057,-1.08953 2.55651,-2.80695 2.55651,-8.34813 0,-3.83703 -0.71372,-7.69196 -1.58604,-8.56653 -0.87232,-0.87457 -4.9167,-1.59012 -8.98752,-1.59012 -4.07082,0 -8.11521,0.71555 -8.98753,1.59012 -2.57798,2.58462 -2.032,15.24407 0.72693,16.85513 3.02779,1.76807 13.02528,1.80463 16.27765,0.0595 z m 0.46587,-39.18559 c 3.0003,-1.1543 3.0003,-15.78846 0,-16.94275 -3.66595,-1.41039 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87456 -1.58603,4.33307 -1.58603,7.68557 0,3.35251 0.71371,6.81101 1.58603,7.68558 1.64502,1.64926 13.8045,2.19618 17.47045,0.7858 z m 0,-39.75299 c 3.0003,-1.15429 3.0003,-15.78845 0,-16.94275 -3.66595,-1.41038 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87457 -1.58603,4.33307 -1.58603,7.68558 0,3.3525 0.71371,6.81101 1.58603,7.68557 1.64502,1.64926 13.8045,2.19619 17.47045,0.7858 z m 0.5046,-39.21368 c 0.87232,-0.87457 1.58604,-4.72951 1.58604,-8.56653 0,-8.09257 -1.7702,-9.71984 -10.57356,-9.71984 -8.80337,0 -10.57356,1.62727 -10.57356,9.71984 0,3.83702 0.71371,7.69196 1.58603,8.56653 0.87232,0.87457 4.91671,1.59012 8.98753,1.59012 4.07082,0 8.1152,-0.71555 8.98752,-1.59012 z m 6.9047,-82.58433 3.07071,-4.493 0.86249,-33.57673 c 0.56571,-22.02292 -0.51063,-35.24838 -1.42808,-36.96705 -2.15439,-4.03588 -9.35774,-6.42677 -19.34616,-6.42125 -10.21122,0.005 -16.75549,3.01486 -18.90955,8.69506 -0.70882,1.86912 -1.28875,17.83614 -1.28875,35.48223 0,27.49791 0.30761,32.52415 2.15212,35.16432 3.58912,5.1374 9.29638,6.89527 20.679,6.36923 9.16778,-0.42368 10.69887,-0.88197 14.20822,-4.25281 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path486" d="m 594.24699,1187.7985 c -1.15909,-0.1861 -2.79951,-1.1442 -3.68761,-2.2365 -1.49488,-1.8388 -1.31131,-8.5525 -1.33055,-68.6798 -0.0137,-42.7931 0.73515,-65.8381 1.58418,-66.8831 3.33535,-4.1049 5.06117,-6.6424 37.3562,-6.6424 19.85047,0 32.4974,1.49 33.95204,2.1545 1.22428,0.5593 4.03684,3.0392 4.89282,4.492 1.41138,2.3954 0.57113,8.6669 0.57113,67.039 v 64.367 l -1.93649,3.9919 -4.71377,2.9045 -30.90991,1.6993 c -20.82649,1.1449 -30.73945,-1.3974 -32.14976,-1.6239 z m 48.27939,-26.876 9.82832,-16.6722 -10.49871,-1.2375 c -6.93861,-0.8179 -18.12085,-0.1436 -24.74598,0 l -11.47394,0.261 12.08666,19.2791 c 6.72092,10.7203 12.32443,15.8272 12.69104,15.4321 0.3666,-0.3951 5.92627,-6.5684 12.11261,-17.0625 z m -0.87571,-43.3626 c 6.55374,-10.4749 10.57311,-17.3167 10.57311,-17.6433 0,-0.3266 -9.16284,-0 -22.78434,-0 -13.62149,0 -21.69277,-0.5851 -21.69277,-0.3178 0,0.5187 19.89711,32.7103 21.45728,34.6835 0.50934,0.6442 -2.27865,3.5495 0.11007,1.4228 1.38644,-1.2344 5.78291,-7.6659 12.33665,-18.1408 z m 1.13238,-46.0729 c 6.22721,-9.9106 9.27066,-15.806 9.27066,-16.0734 0,-0.2673 -9.26032,-0.7017 -22.88182,-0.7017 -13.62149,0 -24.20351,-0.744 -24.20351,-0.5285 0,0.3071 12.54336,18.6285 23.50069,35.8728 1.17961,1.8564 -2.07666,-0.013 -1.06964,-1.0847 0.66128,-0.7037 9.15641,-7.5738 15.38362,-17.4845 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path488" d="m 627.22564,1086.2996 c -1.36595,-2.1565 -6.28035,-9.9327 -10.92087,-17.2805 l -8.43732,-13.3596 21.71147,-0.1218 c 11.9413,-0.067 21.793,-0.04 21.89266,0.06 0.16849,0.1689 -20.53294,33.2929 -21.37902,34.2082 -0.21085,0.2281 -1.50096,-1.3497 -2.86692,-3.5061 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path490" d="m 618.93991,1117.4616 c -5.9568,-9.4452 -10.74845,-17.2554 -10.6481,-17.356 0.10035,-0.1006 9.87754,-0.1281 21.7271,-0.061 l 21.54464,0.1219 -10.771,17.1 c -5.92405,9.405 -10.82749,17.1603 -10.89655,17.2341 -0.069,0.074 -4.99929,-7.5937 -10.95609,-17.0389 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path492" d="m 627.34816,1175.0783 c -1.29113,-2.0355 -6.20112,-9.8147 -10.91108,-17.2872 l -8.56357,-13.5863 21.70844,-0.1218 c 11.93964,-0.067 21.76048,0.1196 21.89378,0.064 1.66501,-0.694 -20.53797,33.3157 -21.38241,34.2108 -0.2266,0.2401 -1.40744,-1.1705 -2.74516,-3.2795 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path494" d="m 705.333,475.35062 0.58572,-25.61496 h 2.58935 c 1.42413,0 3.07073,-0.1852 3.6591,-0.41156 6.23384,-2.39832 6.66628,-39.81075 0.51622,-44.66085 -0.98323,-0.7754 -2.60578,-1.09079 -4.08546,-1.11196 l -3.02606,-0.0433 0.17046,-24.49951 c 0.17521,-25.18178 -0.45706,-26.64286 -3.3757,-33.56049 -0.60015,-1.42246 -0.95981,-2.71801 -0.79924,-2.87899 0.73296,-0.73484 6.77569,9.79438 11.3051,19.6987 8.03987,17.58051 12.92059,24.16575 20.92458,28.23212 5.97386,3.03498 10.12842,3.56131 28.19456,3.57187 l 16.75248,0.01 2.24689,2.25266 c 1.28725,1.29057 2.24478,2.91766 2.24196,3.80967 -0.006,1.78302 -4.60673,10.12411 -8.86443,16.06984 -5.1397,7.17741 -13.21804,16.43802 -27.76099,31.82387 -25.38008,26.85109 -32.85153,36.30476 -38.78153,49.07044 l -2.48145,7.83399 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path496" d="m 551.50149,411.19136 c -0.98602,-0.57578 -1.10996,-1.3398 -1.10661,-6.82131 0.002,-2.873 0.0677,-5.46502 0.14652,-5.76006 0.20727,-0.77576 1.25515,-1.22041 2.87607,-1.22041 h 1.41347 v 7.0274 7.02739 l -1.46028,-0.007 c -0.80316,-0.004 -1.64428,-0.11456 -1.86917,-0.24589 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path498" d="m 705.29823,426.52862 v -21.6925 l 2.74532,0.0832 c 3.12768,0.0948 3.89424,0.4293 4.72483,2.06157 0.61397,1.20659 1.76821,5.63906 2.33099,8.95136 1.27555,7.50746 1.05966,16.78021 -0.57067,24.51085 -1.52786,7.24475 -1.97566,7.77797 -6.53195,7.77797 h -2.69852 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path500" d="m 584.73878,305.9748 c 0.003,-2.26451 1.14147,-4.16777 2.76325,-4.61938 1.23234,-0.34316 46.09771,-0.32639 47.35227,0.0177 0.6001,0.16459 1.31857,0.65313 2.00748,1.36501 1.06534,1.10085 1.37105,1.89697 1.3778,3.58804 l 0.003,0.64418 h -26.75233 -26.75234 l 10e-4,-0.99555 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path502" d="m 744.76749,392.34624 c -7.37403,-1.15256 -12.25912,-3.51316 -17.18139,-8.30249 -4.19,-4.07684 -9.97636,-11.23159 -14.15429,-20.84415 -6.80877,-15.6656 -12.32942,-19.2518 -16.1565,-24.99405 -0.5827,-0.8743 -3.10009,-5.66604 -4.55833,-7.29974 -3.50425,-3.92592 -5.49316,-5.94965 -6.99245,-7.1149 -0.67792,-0.52688 -2.15819,-0.77779 -2.10637,-0.82975 0.1682,-0.16863 10.68177,1.9607 15.83895,3.44149 6.54031,1.87794 9.83649,2.91531 21.26168,6.69147 24.21778,8.00427 37.13651,11.3397 48.9486,12.63781 1.92757,0.21183 4.08294,0.48465 4.78972,0.60624 4.01962,0.69158 8.00385,4.57809 8.87032,8.65275 0.19483,0.9162 0.25245,4.67159 0.19948,13.00069 l -0.0745,11.71234 -0.63074,1.34936 c -0.80435,1.72076 -2.07559,3.36646 -5.20034,6.73215 -1.37555,1.48161 -2.82564,3.19454 -3.22244,3.80651 l -0.72144,1.11267 -13.45364,-0.0227 c -9.97413,-0.0168 -13.9716,-0.10364 -15.45634,-0.33571 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path926" d="m 626.42004,812.0638 c -3.0151,-0.30334 -4.96457,-1.13982 -5.58976,-2.2103 -1.31153,-2.24565 -1.63054,-9.94619 -0.65837,-13.08723 0.61716,-1.99402 1.1237,-2.59841 3.95631,-3.1346 3.07565,-0.5822 10.37998,-0.38743 12.68678,0.34496 1.50914,0.47914 1.69385,0.57767 2.14224,1.78531 0.74868,2.0164 1.22658,7.31549 0.8778,10.29605 -0.36136,3.08801 -0.86268,4.19746 -2.35622,4.92047 -2.0881,1.01083 -7.02388,1.49128 -11.05878,1.08534 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path928" d="m 626.45483,772.42523 c -1.19582,-0.13489 -3.06338,-0.4663 -3.83508,-0.72229 -1.34222,-0.44525 -1.84952,-0.79471 -2.34633,-2.1889 -0.75897,-2.1299 -0.65153,-9.67076 0.10744,-11.80066 0.64277,-1.8038 1.39271,-2.22659 4.72627,-2.66451 2.84021,-0.37312 11.47273,-0.10592 12.66771,0.35154 1.51479,0.57988 2.20815,3.48226 2.20178,8.48923 -0.004,3.1328 -0.28379,5.81187 -0.98109,6.87608 -0.21326,0.32548 -1.09366,1.1394 -1.83309,1.33166 -1.62821,0.42336 -7.87645,0.64719 -10.70761,0.32785 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path930" d="m 626.45219,732.49906 c -1.25777,-0.13165 -3.14347,-0.41083 -3.92609,-0.67038 -1.36508,-0.45271 -1.72145,-0.63254 -2.21967,-2.03069 -0.75897,-2.1299 -0.78566,-9.66466 -0.0267,-11.79456 0.64277,-1.8038 1.59031,-2.26853 4.92387,-2.70646 2.84021,-0.37311 11.2883,-0.0856 12.48328,0.3719 1.51479,0.57988 2.27239,3.48197 2.26602,8.48895 -0.004,3.1328 -0.58408,6.09459 -1.28138,7.1588 -0.21517,0.32839 -0.84775,0.6853 -1.5938,0.87529 -1.65266,0.42087 -7.69669,0.6137 -10.62554,0.30715 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path932" d="m 625.65956,693.89955 c -0.97518,-0.13612 -2.55333,-0.0903 -3.32293,-0.34698 -1.37509,-0.45857 -1.53415,-0.83609 -2.02375,-2.39853 -0.34888,-1.1134 -0.57835,-2.85799 -0.67551,-5.5487 -0.2167,-6.00139 0.52022,-7.93082 3.07167,-9.20691 1.28365,-0.64201 1.83934,-1.06269 7.10382,-1.06269 5.37865,0 5.54929,0.20323 7.00626,0.91889 1.84975,0.90844 2.42826,1.87471 2.83202,4.71762 0.53225,3.74752 -0.17476,11.16443 -1.26107,12.14752 -1.12933,1.02204 -8.85213,1.32114 -12.73051,0.77978 z"/><path id="path489" d="m 379.06905,101.33936 h 13.1901 l 0.037,-8.25531 h 14.1068 c 3.694,0 4.8671,3.29254 4.8671,8.2606 v 75.70196 c 0,3.53235 -3.4085,6.31095 -6.4405,6.31095 h -9.5226 c -2.5944,0 -2.7443,-2.75044 -3.0117,-5.11156 v -5.02502 h -13.0052 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 392.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 320.74985,56.29539 v 15.94604 h 43.5888 V 56.01064 c 0,-2.09826 -1.8726,-3.04523 -3.5597,-3.4883 -12.173,-3.19604 -25.2766,-3.03408 -36.8326,0 -1.8219,0.47838 -3.1965,1.67683 -3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 278.71645,200.68211 c -1.8116,5.3094 -14.3159,15.23177 -26.804,17.54252 0,3.02085 2.1746,7.20824 6.6781,7.20824 h 42.9453 c 9.0444,0 6.7685,24.00009 -7.8827,24.00009 h -14.8228 c -30.7958,10.32445 -58.299,10.53516 -88.3562,0 h -15.6167 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12586 c 6.109,0 8.9689,-3.48568 8.6104,-7.02445 -10.9644,-3.70415 -20.7546,-8.55799 -26.2816,-17.58519 v -3.35273 h 87.2518 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 274.17465,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.5651,3.68761 5.8562,3.68761 17.7306,0.98444 39.2718,0.92676 57.4315,0 3.0517,0 6.0443,-1.82692 6.0104,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="m 258.08445,225.33728 h -45.0418"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 355.50055,191.92715 v 11.14596 c 0,0.96002 -0.737,2.03381 -1.3112,2.03381 h -23.0257 c -0.7228,0 -1.5998,-1.11889 -1.5998,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="m 252.26535,218.07198 h -35.7635"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 128.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27175,0.92888 57.43165,0 3.0517,0 6.0443,-1.83107 6.0102,-3.7933 v -7.74857 h -69.29782 z"/><path id="path509" d="m 91.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 v -58.65862 c 4.57443,-17.00507 13.35533,-35.47833 41.84537,-41.00408 4.97535,0 7.55529,-4.59359 7.55529,-7.40352 26.96999,-35.0496 56.25477,-53.08707 86.30587,-65.49263 h 63.6397 c 27.3731,12.02627 42.6345,29.98675 54.6313,49.5466 V 61.9055 c 0,4.46695 3.7756,9.11203 8.7178,9.11203 h 52.8878 v 128.70726 z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 100.1578,95.57843 H 327.54875 C 327.43015,49.18358 304.14675,1.15062 259.36955,1.15062 L 195.76105,1.8971 C 133.48741,13.03019 120.68895,56.85936 100.1578,95.57843 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 81.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.3167,23.51364 -23.9962,23.51364 H 97.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 216.49175,61.4392 v -1.87954 l 5.5759,-6.74897 c 3.0668,-3.71194 5.5759,-6.75827 5.5759,-6.76966 0,-0.0114 -2.2283,-0.0205 -4.9515,-0.0205 h -4.9514 v -1.75092 -1.75094 h 7.7716 7.7718 v 1.61419 1.61418 l -5.8379,7.04557 -5.8376,7.04554 6.0529,0.0114 6.0532,0.0114 v 1.7297 1.72968 h -8.6113 -8.6116 v -1.87951 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 236.52525,52.97079 V 42.61137 h 2.6255 2.6254 v 8.6079 8.60791 h 6.5824 6.5825 v 1.75151 1.75152 h -9.2079 -9.2079 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 227.42615,152.06817 v -10.42336 h 2.4583 2.4584 v 8.66103 8.66102 h 6.1635 6.1634 v 1.76236 1.76232 h -8.6218 -8.6218 z"/></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg
new file mode 100644
index 00000000..c073c9c0
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000 1300" xml:space="preserve"><metadata id="metadata161"/><style id="style2" type="text/css">.st0{opacity:.1}.st1{fill:#02c5e5}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><g id="layer1"><g id="g344" transform="translate(-64,299.7467)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="237.9 448.9 225.8 469.9 250 469.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="250 605.9 237.9 626.9 225.8 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="169.9 525.8 148.9 537.9 169.9 550" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="326.9 537.9 305.9 550 305.9 525.8" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="M 389.22472,464.93186 V 72.687962 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-3"/></g><g id="g315" transform="translate(56.713,299.7467)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-6"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><path id="path4136" d="m 680.8329,101.33936 h -13.19009 l -0.0372,-8.255307 h -14.10678 c -3.694,0 -4.86707,3.292534 -4.86707,8.260597 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 667.63443,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 739.15217,56.29539 v 15.946041 h -43.5888 V 56.010642 c 0,-2.098267 1.87258,-3.045238 3.55963,-3.488308 12.17302,-3.196036 25.27663,-3.034074 36.83267,0 1.82189,0.478381 3.1965,1.676837 3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 781.18551,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 785.72736,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 801.81755,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 704.71423,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 807.6366,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 931.20675,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 858.45697,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 968.76047,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.478328 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.593593 -7.55529,-7.403519 C 917.38071,31.981408 888.09597,13.94394 858.0448,1.5383817 H 794.40512 C 767.03205,13.564651 751.77061,31.525124 739.77382,51.084979 v 10.820524 c 0,4.466942 -3.77561,9.112021 -8.71777,9.112021 H 678.16828 V 199.72479 Z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 959.74418,95.578426 H 732.35325 C 732.47179,49.183575 755.75521,1.15062 800.53245,1.15062 l 63.60853,0.7464785 c 62.27359,11.1330875 75.07205,54.9622645 95.6032,93.6813275 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 978.40756,126.18349 H 730.44883 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 815.30427,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 824.38936,52.916016 V 42.513284 l 5.50031,0.01822 c 5.86555,0.01821 5.99551,0.02347 7.21251,0.236844 0.72764,0.127791 1.2063,0.273954 1.73262,0.529704 0.56119,0.272632 0.92919,0.536857 1.3444,0.965169 0.6865,0.708209 1.17119,1.612413 1.4232,2.655056 0.10465,0.436493 0.11392,0.546291 0.11623,1.401798 6.9e-4,0.725362 -0.0233,1.008267 -0.0743,1.294521 -0.49307,2.372679 -2.15713,3.863382 -4.92053,4.408664 -0.52052,0.102747 -0.58004,0.12279 -0.5089,0.173128 0.044,0.0312 0.27805,0.18384 0.51935,0.338992 1.26535,0.81414 2.04879,1.63119 3.24347,3.383274 0.43519,0.6382 3.38993,5.242662 3.43201,5.348069 0.0233,0.04234 -0.49075,0.05101 -2.51118,0.04215 l -2.53257,-0.0114 -1.89628,-2.766293 c -2.70088,-3.939608 -3.00426,-4.356325 -3.57776,-4.912496 -0.79112,-0.767048 -1.35952,-0.94266 -3.17329,-0.980344 L 828.653,54.61555 v 4.3512 4.351165 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.663034 c 0.70021,-0.07582 1.02521,-0.153763 1.4046,-0.337001 0.60955,-0.294507 1.03662,-0.843043 1.20307,-1.545677 0.0907,-0.379282 0.0884,-1.172853 -0.002,-1.51464 -0.27525,-1.037227 -1.09727,-1.677094 -2.30428,-1.793635 -0.22549,-0.02279 -1.74122,-0.03988 -3.36922,-0.04055 l -2.96011,-0.0016 v 2.663058 2.663038 l 2.78783,-0.02279 c 1.66078,-0.01369 2.97079,-0.0419 3.23998,-0.07107 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 804.36779,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path id="path489" d="m 314.06908,101.33936 h 13.19009 l 0.0372,-8.255307 h 14.10678 c 3.694,0 4.86707,3.292534 4.86707,8.260597 v 75.70196 c 0,3.53235 -3.40852,6.31095 -6.44045,6.31095 h -9.52259 c -2.5944,0 -2.74434,-2.75044 -3.01169,-5.11156 v -5.02502 H 314.2902 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 327.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 255.74981,56.29539 v 15.946041 h 43.5888 V 56.010642 c 0,-2.098267 -1.87258,-3.045238 -3.55963,-3.488308 -12.17302,-3.196036 -25.27663,-3.034074 -36.83267,0 -1.82189,0.478381 -3.1965,1.676837 -3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 213.71647,200.68211 c -1.81167,5.3094 -14.31597,15.23177 -26.80398,17.54252 0,3.02085 2.17456,7.20824 6.67803,7.20824 h 42.94533 c 9.04439,0 6.76848,24.00009 -7.88272,24.00009 h -14.82275 c -30.79579,10.32445 -58.29906,10.53516 -88.35628,0 h -15.61665 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12588 c 6.10893,0 8.96884,-3.48568 8.61035,-7.02445 -10.9644,-3.70415 -20.75456,-8.55799 -26.28159,-17.58519 v -3.35273 h 87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 209.17462,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.56512,3.68761 5.85626,3.68761 17.73054,0.98444 39.27177,0.92676 57.43145,0 3.05168,0 6.04433,-1.82692 6.01039,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="M 193.08443,225.33728 H 148.04265"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 290.50058,191.92715 v 11.14596 c 0,0.96002 -0.73701,2.03381 -1.3112,2.03381 h -23.02573 c -0.72278,0 -1.59984,-1.11889 -1.59984,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="M 187.26538,218.07198 H 151.50187"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 63.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27172,0.92888 57.43168,0 3.05166,0 6.04429,-1.83107 6.01013,-3.7933 v -7.74857 H 63.69523 Z"/><path id="path509" d="m 26.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 V 115.43861 C 5.72505,98.43354 14.50595,79.960282 42.99599,74.43453 c 4.97535,0 7.55529,-4.593593 7.55529,-7.403519 26.96999,-35.049603 56.25473,-53.087071 86.3059,-65.4926293 h 63.63968 c 27.37307,12.0262693 42.63451,29.9867423 54.6313,49.5465973 v 10.820524 c 0,4.466942 3.77561,9.112021 8.71777,9.112021 H 316.7337 V 199.72479 Z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 35.1578,95.578426 H 262.54873 C 262.43019,49.183575 239.14677,1.15062 194.36953,1.15062 L 130.761,1.8970985 C 68.48741,13.030186 55.68895,56.859363 35.1578,95.578426 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 16.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.31669,23.51364 -23.99616,23.51364 H 32.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 151.49179,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 171.52526,52.970786 V 42.611364 h 2.62547 2.62545 v 8.607904 8.607907 h 6.5824 6.58243 v 1.751518 1.751517 h -9.20788 -9.20787 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 162.42612,152.06817 v -10.42336 h 2.45836 2.45836 v 8.66103 8.66102 h 6.16349 6.16346 v 1.76236 1.76232 h -8.62185 -8.62182 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path979" d="m 724.21326,200.03615 v 6.10386 h 9.9129 V 199.759 Z"/></g></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg
new file mode 100644
index 00000000..f4f12514
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st0{opacity:.1}.st2{fill:#fff}</style><style id="style2-6" type="text/css">.st0{opacity:.1}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path139" d="m 336.48913,612.01334 c -4.48491,-0.96172 -17.26511,-2.20937 -14.21934,-5.20076 l -1.59612,-5.33256 4.69156,-28.97943 c -21.87609,0.35049 0.88574,-29.59975 1.14094,-31.15228 0.67186,-4.0867 0.63712,-6.98639 4.0089,-9.33254 4.31967,-3.0057 6.13876,-6.05239 15.39769,-6.04934 6.18575,0.002 6.23657,4.51842 7.63527,4.8094 2.83752,0.59027 9.26915,0.22171 11.12017,2.22098 1.29357,1.39718 -1.70326,4.54462 -1.05568,6.52843 l 0.45372,1.38995 3.01931,28.03144 c 2.5809,23.96121 -1.28772,28.6331 -1.52389,30.69067 -0.50713,4.41767 -1.36999,7.75168 -2.71808,9.24386 -0.75196,0.83233 -6.13557,2.17746 -7.4235,2.75447 -0.6956,0.31163 -1.65288,2.59566 -4.83555,2.70854 -6.19176,0.21959 -12.78623,-2.05009 -14.09542,-2.33083 z m 7.03011,-22.69305 c 2.05969,-1.10868 2.82647,-2.34895 4.0826,-6.60361 0.94044,-3.18536 1.27937,-3.92467 2.00093,-4.36459 0.80192,-0.48891 1.26549,-0.45046 1.96409,0.16291 0.71152,0.62473 1.00895,1.51574 1.00895,3.02259 0,1.56253 -0.45686,2.45036 -1.57367,3.05821 -0.47337,0.25764 -0.98442,0.46843 -1.13567,0.46843 -0.46699,0 -0.51735,0.31657 -0.38564,2.42443 l 0.12741,2.03924 0.99608,-0.11707 c 1.81227,-0.21299 3.67586,-1.28059 4.58801,-2.62833 0.73213,-1.08177 1.05118,-2.01238 1.28038,-3.73464 0.52157,-3.91942 -0.80021,-7.14962 -3.48153,-8.50821 -0.95096,-0.48184 -1.18331,-0.52396 -2.89025,-0.52396 -1.61522,0 -1.95941,0.0547 -2.65165,0.42127 -2.42724,1.2854 -3.01034,2.27706 -4.76741,8.10775 -0.81484,2.70397 -1.68257,3.5027 -3.32487,3.06047 -0.81096,-0.21836 -1.7952,-1.15122 -2.09882,-1.98922 -0.27463,-0.75801 -0.29371,-2.48144 -0.0369,-3.33844 0.11098,-0.37041 0.44343,-0.96663 0.73878,-1.32494 0.5549,-0.6732 2.03724,-1.48499 2.71713,-1.48802 0.21302,-8.8e-4 0.44057,-0.0879 0.50566,-0.19321 0.0651,-0.10531 0.0206,-1.09911 -0.0989,-2.20844 l -0.21726,-2.01697 -0.73033,0.1088 c -1.04346,0.15545 -2.73301,0.73031 -3.56485,1.21291 -1.00575,0.5835 -2.3307,2.05885 -2.82441,3.14502 -0.60372,1.32822 -0.8601,3.09117 -0.73888,5.08087 0.2291,3.76062 1.69285,6.01606 4.59237,7.07626 0.73645,0.26928 1.31213,0.32792 2.86609,0.29196 1.83004,-0.0424 2.0098,-0.0801 3.05264,-0.64147 z m 12.41532,-19.9635 v -2.27241 l -4.3514,-0.0924 c -4.61309,-0.098 -4.53528,-0.082 -4.77362,-0.9766 -0.38253,-1.43579 0.87656,-2.86072 4.54388,-5.14234 1.30429,-0.81146 2.86862,-1.78392 3.47629,-2.16102 l 1.10485,-0.68564 v -2.47936 c 0,-1.37252 -0.0718,-2.47937 -0.16095,-2.47937 -0.2065,0 -2.12366,1.07629 -5.14235,2.88691 -1.67092,1.00223 -2.71254,1.76796 -3.47394,2.55381 l -1.08745,1.12238 -0.2181,-0.6741 c -0.55224,-1.70685 -1.65782,-3.08363 -3.04416,-3.79088 -0.90425,-0.46132 -2.76434,-0.67068 -4.28507,-0.4823 -2.32805,0.28839 -4.02881,1.54469 -4.62261,3.41459 -0.2868,0.90314 -0.54591,5.91584 -0.57837,11.18885 l -0.0144,2.34229 h 11.3137 11.31371 z"/><g id="g315" transform="translate(0,300.03245)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><ellipse id="ellipse382" cx="344.639" cy="859.606" rx="15.571" ry="14.069" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path384" d="m 443.0983,809.82781 v 45.80985" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path386" d="m 436.0092,815.74618 v 36.37333" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path388" d="m 355.92023,980.61127 c -0.159,2.38632 -0.9339,4.18348 -2.3494,5.44717 -1.0538,0.94086 -2.4969,1.60298 -4.1869,1.92092 -0.3864,0.0726 -1.0871,0.1771 -1.0975,0.16314 0,-0.005 -0.093,-0.85306 -0.2017,-1.88773 -0.1082,-1.03464 -0.2053,-1.93454 -0.2156,-1.9998 -0.018,-0.10426 -0.01,-0.11846 0.052,-0.11846 0.1214,0 0.6621,-0.12294 1.0604,-0.24083 1.8948,-0.56173 2.9076,-1.69881 3.1357,-3.52037 0.053,-0.4186 0.023,-1.49252 -0.051,-1.88234 -0.1958,-1.02944 -0.6378,-1.79009 -1.336,-2.30018 -0.5453,-0.39839 -0.9906,-0.54269 -1.6797,-0.54425 -0.4911,0 -0.7649,0.0565 -1.0906,0.22816 -0.224,0.11845 -0.5342,0.39899 -0.7138,0.64552 -0.4284,0.5885 -0.6382,1.17335 -1.3991,3.89925 -0.4752,1.70296 -0.7598,2.51481 -1.1909,3.39834 -0.584,1.19653 -1.3563,2.06447 -2.414,2.7127 -0.5828,0.35721 -1.3337,0.64064 -2.0474,0.7727 -0.3392,0.0631 -0.4902,0.0716 -1.1851,0.0709 -0.6888,-7.5e-4 -0.842,-0.01 -1.1342,-0.0703 -1.7103,-0.34894 -3.1451,-1.32436 -3.9859,-2.70946 -0.3778,-0.62245 -0.6928,-1.42824 -0.8702,-2.22642 -0.3894,-1.7521 -0.3112,-4.07304 0.1924,-5.71076 0.2323,-0.7556 0.6307,-1.54303 1.0637,-2.10262 0.2976,-0.38477 1.0376,-1.06011 1.4626,-1.33492 0.6802,-0.43973 1.5737,-0.79266 2.4151,-0.95396 0.4254,-0.0815 0.9688,-0.14541 1.2361,-0.14541 h 0.1571 l 2e-4,0.18183 c 2e-4,0.0998 0.039,0.97141 0.087,1.93652 0.048,0.96511 0.086,1.80485 0.086,1.86617 l 10e-5,0.11137 -0.3029,0.0565 c -0.6791,0.12626 -1.358,0.40173 -1.7702,0.71779 -0.8027,0.61542 -1.1472,1.52476 -1.1467,3.02784 3e-4,0.9899 0.1461,1.66912 0.5004,2.33009 0.4111,0.76692 0.8552,1.07989 1.5814,1.1146 0.5403,0.0263 0.9144,-0.092 1.2917,-0.40687 0.6036,-0.50373 1.0028,-1.42843 1.6845,-3.90103 0.5306,-1.92496 0.7696,-2.6569 1.1769,-3.6043 0.7236,-1.68302 1.723,-2.76077 3.1653,-3.41339 0.8627,-0.39031 1.6574,-0.56193 2.8045,-0.60571 1.3619,-0.0523 2.6128,0.24529 3.8083,0.90462 1.3364,0.73709 2.2925,1.87859 2.8381,3.38818 0.4756,1.31608 0.6841,3.06752 0.5698,4.78495 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path390" d="m 344.68166,571.55323 -11.22758,0.0524 0.0282,-4.64898 c 0.0146,-2.39871 0.018,-4.79751 0.034,-5.29725 0.1201,-2.99844 0.50834,-4.47151 1.80242,-5.57094 1.43938,-1.29933 3.86276,-1.68857 6.05962,-1.28878 1.22398,0.1999 2.1495,0.86284 2.97159,1.66242 0.75529,0.79959 1.34588,1.99896 1.58337,3.29829 0.053,0.29984 0.0886,0.10698 0.12964,0.007 0.026,0 0.17696,-0.007 0.36596,-0.20693 0.79258,-1.09943 1.50437,-1.8495 2.85325,-2.64909 0.78279,-0.49974 1.13628,-0.74914 4.08763,-2.44826 l 2.49546,-1.39927 0.01,2.39875 c 0,1.99896 -2e-4,2.4987 -0.034,2.4987 -0.023,0 -1.34447,0.89954 -2.93445,1.79907 -4.59312,2.79854 -5.0351,3.37378 -5.57969,3.97346 -0.54019,0.69964 -0.66221,0.81512 -0.69151,2.41429 l 0.48716,0.75844 4.08351,0.26903 4.69846,0.0106 -0.0199,2.16917 0.0199,2.25025 -11.13382,-0.0473 z m -1.74891,-9.39408 c -0.041,-0.69963 -0.114,-1.29932 -0.18719,-1.49922 -0.2217,-0.79958 -0.88159,-1.39927 -1.75178,-1.59917 -0.32459,-0.1 -1.14798,-0.1 -1.50817,-0.1 -0.87379,0.1 -1.48218,0.49974 -1.85017,1.19938 -0.3531,0.69964 -0.3777,0.99948 -0.3791,4.69756 l -7e-4,2.4987 h 2.85636 2.85645 v -2.2988 c 0,-1.29933 -0.018,-2.59865 -0.036,-2.8985 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path392" d="m 333.0763,580.70071 c 0.2699,-3.09839 1.47058,-5.09735 3.82724,-6.39667 0.94539,-0.49974 2.47236,-0.99948 3.66664,-1.09943 h 0.2144 l 0.021,0.1 c 0.037,0.19989 0.41959,3.89797 0.40439,3.89797 -0.01,0 -0.17189,0.1 -0.36389,0.1 -0.1921,0 -0.53819,0.0999 -0.76929,0.1999 -1.79067,0.49974 -2.78005,1.59916 -3.10355,3.19833 -0.099,0.49974 -0.1074,1.59917 -0.015,2.19886 0.1217,0.69964 0.322,1.19938 0.62179,1.59917 0.41149,0.59969 0.98798,0.99948 1.60627,1.19938 0.3497,0.0999 1.05159,0.19989 1.39958,0.0999 0.68299,-0.19989 1.12958,-0.49974 1.53758,-1.29932 0.28619,-0.49974 0.48609,-1.09943 1.12488,-3.39823 0.58179,-2.09891 0.89518,-2.99845 1.46878,-3.99793 0.54769,-0.99948 1.29527,-1.69911 2.25086,-2.2988 1.01618,-0.59969 2.16996,-0.89953 3.44104,-0.79959 1.09519,0 2.11077,0.29985 3.03455,0.89954 0.67949,0.39979 1.15789,0.79958 1.62308,1.49922 0.94818,1.29932 1.41878,2.99844 1.41828,5.09735 -5e-4,2.39875 -0.5283,4.19782 -1.61348,5.59709 -0.28049,0.29984 -0.87698,0.89953 -1.25648,1.09943 -1.02518,0.69963 -2.17746,1.09942 -3.55564,1.19937 -0.2116,0 -0.38909,0 -0.39449,0 -0.015,0 -0.2131,-4.09787 -0.2004,-4.09787 0.01,0 0.1496,-0.0999 0.31999,-0.0999 0.96079,-0.1999 1.73388,-0.59969 2.16607,-1.09943 0.33459,-0.3998 0.56069,-0.89954 0.68789,-1.49922 0.1015,-0.49974 0.1113,-1.69912 0.018,-2.19886 -0.1453,-0.89953 -0.46589,-1.59917 -0.92189,-1.99896 -0.48339,-0.49974 -1.31478,-0.59969 -1.98367,-0.29985 -0.30419,0.0999 -0.66298,0.3998 -0.87728,0.69964 -0.397,0.59969 -0.77619,1.69912 -1.28808,3.59813 -0.61799,2.19886 -1.08688,3.49818 -1.64607,4.49766 -0.90499,1.59917 -2.40657,2.59865 -4.21394,2.99844 -0.65499,0.1 -1.14148,0.1 -1.88937,0.1 -0.52549,0 -0.75938,0 -1.08948,-0.1 -1.82277,-0.39979 -3.39374,-1.29932 -4.32833,-2.69859 -0.65799,-0.99948 -1.07878,-2.19886 -1.27778,-3.79803 -0.053,-0.39979 -0.097,-2.2988 -0.063,-2.6986 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path394" d="m 344.34473,966.1041 h -11.2417 v -2.07865 -2.07863 h 9.3507 9.3505 v -5.19669 -5.19663 h 1.8911 1.8912 v 7.27527 7.27533 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path396" d="m 409.8518,320.05567 -2.8025,-2.94026 -2.1084,-1.796 -3.8978,-2.62047 -4.9398,-2.55642 -3.8113,-1.26102 -3.8729,-0.82355 -1.3897,-0.20254 -2.8884,-0.16657 h -57.7923 l -1.5715,0.14912 -1.7697,0.23885 -1.7748,0.23784 -2.7296,0.54225 -2.3129,0.60501 -2.4432,0.75415 -2.944,0.94164 -2.1288,0.90223 -3.8498,1.71494 -2.7574,1.53514 -2.1058,1.19382 -3.235,2.15931 -2.4201,1.63397 -1.436,1.20278 -1.896,1.44906 -3.2118,2.6021 -2.4228,2.54068 -4.259,4.68887 -2.5995,3.24851 -1.6774,2.6235 -1.271,2.18323 -1.9119,3.72736 -0.727,1.6468 -1.1613,2.96158 -0.6623,2.59781 -0.7848,3.27106 -0.3398,2.68009 -0.048,2.38299 v 3.99567 2.84426 875.03454 l 0.1638,2.4919 0.3452,3.3929 1.2989,4.7686 1.2397,3.7743 3.6049,7.2541 2.5738,4.0559 2.4685,3.1987 1.4819,1.9751 2.6694,2.8626 3.0699,3.022 2.1765,1.9253 4.0187,3.1181 4.1145,2.8537 2.3075,1.2731 3.5235,1.8455 3.6903,1.6798 4.1541,1.4538 3.7259,1.1675 3.6825,0.7441 3.285,0.4416 3.0789,0.2674 h 56.728 l 2.2738,-0.2161 3.6621,-0.6453 2.1372,-0.5088 2.6035,-0.8999 3.7077,-1.5118 3.7208,-1.891 3.1188,-1.9598 2.4944,-2.0592 3.0857,-2.8789 3.1141,-3.8291 2.3879,-3.9155 1.3793,-3.2339 1.0698,-2.9013 0.8145,-3.3519 0.4154,-3.6021 0.024,-2.1424 V 343.15522 l -0.2807,-2.93341 -0.6388,-3.84483 -1.3177,-4.25655 -1.5322,-3.68324 -2.5337,-4.45711 -1.9699,-2.57666 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path398" d="m 395.3929,1180.0491 v 6.0661 l 0.2504,2.2569 -0.22889,0.3633 0.0188,0.4323 0.0368,0.983 -1.0319,1.3186 -1.91624,1.5403 -1.8286,1.4972 -2.1313,1.0814 -1.9039,0.5267 -1.6018,0.1436 h -79.7814 l -1.9951,-0.4092 -2.2181,-0.8515 -1.5437,-0.8939 -1.324,-1.0482 -0.8339,-0.9964 -0.9297,-1.4644 -0.5711,-1.0947 -0.331,-0.8522 -0.2214,-1.445 v -0.9701 -816.23528 l 0.1524,-0.78853 0.1354,-0.61772 0.2239,-0.77581 0.2629,-0.76027 0.5285,-1.02162 0.7718,-1.1054 0.9507,-1.04883 1.5188,-1.1948 1.1498,-0.70115 1.3513,-0.54994 1.7628,-0.48373 1.567,-0.17203 h 79.0926 l 1.0991,0.0989 1.3891,0.27672 2.2207,0.74493 1.1905,0.67498 1.4954,1.14485 0.8938,0.8516 1.1289,1.64893 0.7411,1.63916 0.386,1.57396 0.05,1.06242 c -0.0804,114.31284 -0.10418,228.63693 -0.0983,342.96694 0.008,155.52282 0.0712,311.05662 0.12178,466.58792 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path400" d="m 280.0489,334.04973 -2.8746,2.16498 -1.3945,1.27122 -1.1064,1.18868 -1.3392,1.49729 -1.3821,1.73597 -1.1375,1.54737 -1.1471,1.61493 -1.7633,2.77824 -1.1335,1.98857 -0.9191,1.69028 -1.3324,2.59146 -1.1121,2.32402 -1.5658,3.3824 -0.6357,1.21716 -0.7728,1.8524 -0.7249,1.7502 -0.989,2.11092 -1.0447,2.26153 -0.86,1.70122 -0.7487,1.45807 -0.7784,1.50072 -1.1616,2.03112 -0.6994,1.16648 -1.3216,2.11047 -1.1613,1.58472 -0.9183,1.1248 -1.4672,1.69512 -1.42,1.41779 -1.9934,1.72491 -2.2557,1.72298 -2.1512,1.20455 -1.3718,0.68514 -3.115,1.23076 -4.1538,1.06111 -3.0868,0.4675 -3.2213,0.30214 h -28.4829 l -0.9465,0.0522 -0.9784,0.35707 -1.1635,0.4739 -0.9822,0.69974 -1.0146,1.07545 -0.9282,1.35489 -0.6502,1.7225 -0.1277,1.59156 0.296,1.44131 0.7415,1.59064 1.9905,3.44769 2.4225,4.15209 2.3354,3.53006 1.3741,1.96135 1.2426,1.70362 1.4133,1.82618 1.3411,1.74059 2.1466,2.65906 1.9723,2.30436 1.0859,1.37163 2.4142,2.76344 1.3089,1.52486 3.0336,3.39354 1.5816,1.80314 1.3444,1.31094 2.4631,2.62274 1.0462,1.088 4.8462,5.01965 3.6011,3.76598 1.7432,1.82423 2.1054,2.24013 6.0616,6.47629 2.3937,2.58723 2.014,2.19763 1.6282,1.85126 1.1405,1.25224 1.6465,1.98007 1.726,2.18054 1.5288,1.91466 1.2553,1.47803 1.1294,1.5201 1.6519,2.24592 1.1514,1.59813 1.313,1.80747 1.0891,1.73386 1.8619,2.95681 1.9716,3.31485 1.215,2.46611 1.3695,2.68245 0.9533,2.4215 1.0707,2.90707 0.7627,2.01532 h 0.6246"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path402" d="m 419.6848,525.27774 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5718 -0.1723 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path404" d="m 419.7599,446.71674 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4608,1.28829 0.064,0.91052 0.158,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.07,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3264,4.36272 -0.1217,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5717 -0.1724 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path406" d="m 419.3182,991.21629 0.7067,0.005 1.1504,0.26365 0.9444,0.76195 0.3328,0.70813 v 46.67098 l -0.351,0.8325 -1.1666,0.8966 -0.7662,0.1774 -0.7976,-0.036 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path408" d="m 292.23542,321.94382 -2.85482,0.19193 -3.5205,0.79532 -3.2999,0.79136 -3.3568,0.85492 -10.5848,3.04972 -8.2427,2.61122 -6.9829,2.30208 -8.1913,2.71333 -6.855,2.11775 -7.5618,2.21755 -3.0235,0.89028 -3.0148,0.78091 -2.5919,0.65281 -4.3968,1.00847 -3.4498,0.73028 -4.1489,0.73001 -5.6739,0.74708 -2.2602,0.25755 -2.5162,0.19354 -1.5131,0.53719 -1.7144,0.82362 -1.1537,0.80424 -0.8192,0.61627 -1.0935,1.16923 -1.2892,1.65867 -1.0363,2.0311 -0.4006,1.59894 -0.1889,1.03517 v 22.38615 l 0.1909,1.30564 0.4958,1.40886 0.8296,1.64975 0.8332,1.21754 1.2656,1.51781 1.473,1.67519 1.7472,1.806 1.5258,1.66687 1.0269,1.42626 0.5157,0.92256"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path410" d="m 419.5504,789.12692 1.0104,0.39157 1.2284,0.93414 1.2742,1.0266 1.3335,1.34755 1.3498,1.58941 1.4074,1.79596 1.068,1.4886 0.8509,1.19973 0.8928,1.39146 0.9973,1.62576 0.6021,1.24333 0.8025,1.68804 0.9324,1.96316 0.9148,2.22486 0.6262,1.90738 0.5734,2.0049 0.5948,2.79681 0.1489,0.35893 1.1814,-0.13758 0.9744,-0.18453 1.2915,-0.53944 1.0017,-0.68907 1.1544,-0.99535 0.604,-0.85004 0.4934,-1.12029 0.3702,-1.37331 v -45.33419 l 0.2034,-1.17653 0.748,-1.09495 0.8786,-0.84648 1.1084,-0.65922 1.6277,-0.61299 1.9995,-0.31181 2.419,-0.0432 3.3419,0.50976 2.789,1.02605 1.7576,0.92574 1.4806,0.99459 2.1054,1.92583 1.357,1.78977 0.7746,1.80358 0.5382,2.14337 0.1755,1.82459 v 15.36545 l 0.7426,2.32837 0.8151,3.04194 0.6637,2.10231 1.4461,5.39684 0.1081,0.54415 0.3624,1.61807 0.4384,2.00735 0.5281,2.58998 0.5111,2.93668 0.532,3.40847 0.5218,3.68177 0.2738,2.55863 0.1742,1.97306 0.125,1.76412 0.1687,2.52444 0.093,2.5116 0.1008,2.95717 0.032,3.58916 -0.1372,3.61839 -0.1588,3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path412" d="m 419.5504,878.18361 1.0104,-0.39157 1.2284,-0.93414 1.2742,-1.0266 1.3335,-1.34755 1.3498,-1.58941 1.4074,-1.79596 1.068,-1.4886 0.8509,-1.19973 0.8928,-1.39146 0.9973,-1.62576 0.6021,-1.24333 0.8025,-1.68804 0.9324,-1.96316 0.9148,-2.22486 0.6262,-1.90738 0.5734,-2.0049 0.5948,-2.79681 0.1489,-0.35893 1.1814,0.13758 0.9744,0.18453 1.2915,0.53944 1.0017,0.68907 1.1544,0.99535 0.604,0.85004 0.4934,1.12029 0.3702,1.37331 v 45.33419 l 0.2034,1.17653 0.748,1.09495 0.8786,0.84648 1.1084,0.65922 1.6277,0.61299 1.9995,0.31181 2.419,0.0432 3.3419,-0.50976 2.789,-1.02605 1.7576,-0.92574 1.4806,-0.99459 2.1054,-1.92583 1.357,-1.78977 0.7746,-1.80358 0.5382,-2.14337 0.1755,-1.82459 v -15.36545 l 0.7426,-2.32837 0.8151,-3.04194 0.6637,-2.10231 1.4461,-5.39684 0.1081,-0.54415 0.3624,-1.61807 0.4384,-2.00735 0.5281,-2.58998 0.5111,-2.93668 0.532,-3.40847 0.5218,-3.68177 0.2738,-2.55863 0.1742,-1.97306 0.125,-1.76412 0.1687,-2.52444 0.093,-2.5116 0.1008,-2.95717 0.032,-3.58916 -0.1372,-3.61839 -0.1588,-3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path414" d="m 345.6694,529.78706 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 -1.2064,0.95657 -1.075,1.06404 -1.1014,1.41493 -0.594,1.14722 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69762 l 0.1365,1.11638 0.2065,0.99097 0.3274,0.9147 0.2958,0.88818 0.5023,0.98607 0.7034,1.07023 0.7271,0.83072 1.1425,1.22917 0.9548,0.84847 1.1231,0.73807 1.3029,0.76185 1.5781,0.61856 1.753,0.41994 1.6248,0.25206 1.9291,0.0355 12.21761,-0.15231 1.24069,0.009 1.4416,-0.26481 1.209,-0.3538 1.3406,-0.58952 1.2548,-0.64457 0.9072,-0.5388 1.0383,-0.81994 0.7108,-0.73783 0.6713,-0.63536 1.2672,-1.78476 1.0821,-2.39096 0.4226,-1.73078 0.032,-1.77014 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path416" d="m 345.6694,929.08474 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 c -0.40213,0.31886 -0.80427,-0.0101 -1.2064,0.95657 -1.1612,-0.13384 -0.80827,0.40421 -1.2124,0.60632 l -1.03457,1.59803 -0.52343,1.42184 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69758 l 0.1365,1.1164 0.2065,0.991 0.3274,0.9147 0.2958,0.8882 0.5023,0.986 0.7034,1.0703 0.7271,0.8307 1.1425,1.2292 0.9548,0.8484 1.1231,0.7381 1.3029,0.7618 1.5781,0.6186 0.84467,0.2023 0.90833,0.2176 1.6248,0.2521 1.9291,0.035 h 12.2138 l 1.2445,-0.1435 1.4416,-0.2648 1.209,-0.3538 1.3406,-0.5895 1.2548,-0.6446 0.9072,-0.5388 1.0383,-0.8199 0.7108,-0.7378 0.6713,-0.6354 1.2672,-1.7847 1.0821,-2.391 0.4226,-1.7308 0.032,-1.77012 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path426" d="m 269.3709,404.13671 h -4.9495 l -1.0113,0.19773 -1.022,0.65678 -0.7694,0.84217 -0.623,1.27551 -0.4117,1.3715 -0.6037,2.17152 -0.5303,2.14305 -0.3827,1.9667 -0.3142,1.95063 -0.2528,2.01116 -0.2212,2.18086 -0.1418,2.35493 -0.046,2.05813 0.034,2.89349 0.1866,2.92296 0.2597,3.11808 0.3257,2.74124 0.4726,2.4298 0.3837,2.06422 0.6228,2.42502 0.4876,1.70136 0.5673,1.13322 0.656,0.75539 0.7893,0.54624 0.78,0.31802 0.8271,0.091 h 5.1673 0.2296 v -44.33098 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path428" d="m 419.3062,396.58247 h 3.3623 l 0.9525,0.25724 0.8868,0.75004 0.3797,1.09319 v 10.77754 l -0.3997,0.99826 -0.4739,0.71234 -0.6363,0.44149 -0.5074,0.1596 h -3.3662 -0.2116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path430" d="m 368.2112,1052.977 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path432" d="m 368.2112,1097.1347 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path434" d="m 368.2112,1141.3197 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path436" d="m 343.5847,1042.2128 h -27.013 l -1.8698,0.2799 -1.342,0.3586 -1.606,0.6627 -1.1661,0.7504 -1.1412,0.8758 -0.7833,0.8235 -0.7034,0.7948 -0.6319,1.1103 -0.4797,0.9867 -0.3453,1.0256 -0.2487,1.1948 -0.069,0.83 v 125.1345 l 0.052,0.8702 0.1667,1.0482 0.4222,1.1949 0.7328,1.4918 0.8537,1.1485 1.4176,1.3519 1.1779,0.9169 1.5965,0.8574 1.9127,0.6145 1.7443,0.195 h 57.292 l 1.482,-0.1169 1.5379,-0.379 1.0258,-0.4189 1.0471,-0.555 0.7983,-0.4851 1.0868,-0.8153 1.1798,-1.2764 0.6871,-0.9185 0.4367,-0.7747 0.3972,-0.7651 0.3643,-1.035 0.1713,-0.7948 0.086,-1.2186 v -125.1426 l -0.076,-1.0984 -0.204,-0.9502 -0.2266,-0.7979 -0.3429,-0.7631 -0.7969,-1.4695 -0.8643,-1.1417 -1.3636,-1.2219 -1.4025,-0.9472 -0.7682,-0.4017 -1.6691,-0.5921 -1.312,-0.2496 -1.4844,-0.1821 -1.158,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path438" d="m 390.4523,307.66577 v -3.14841 l -0.3715,-1.45506 -0.7559,-1.06735 -1.1876,-0.97885 -1.7025,-0.48365 h -45.228 l -1.5835,0.18859 -1.2132,0.58802 -0.8602,0.6336 -0.6208,0.61481 -0.7767,1.21911 -0.2726,1.3989 v 2.48519 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path440" d="m 419.68509,599.75674 h 3.3148 l 1.2108,0.19587 1.41971,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.28051,0.22452 h -4.5718 -0.1723 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path506" d="m 420.36151,634.93249 v -34.75633 l 2.0263,0.23815 c 2.75467,0.32376 4.80203,1.57598 5.69709,3.48449 1.06072,2.26176 1.52361,9.71023 1.72256,27.71794 0.14637,13.24854 0.0672,17.02245 -0.52828,25.19166 -0.77583,10.64303 -0.85918,10.95183 -3.29112,12.19251 -0.89452,0.45635 -2.06849,0.68792 -3.48749,0.68792 h -2.13906 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path508" d="m 420.36151,560.56402 v -34.75143 l 1.85933,0.15785 c 2.39951,0.20371 4.31925,1.13642 5.48512,2.66497 0.83656,1.09678 0.97668,1.7388 1.39976,6.41356 0.25858,2.85712 0.56214,12.52586 0.67458,21.48608 0.1781,14.19187 0.11309,17.54027 -0.50447,25.983 l -0.70891,9.69168 -1.16519,1.20216 c -1.30344,1.34481 -2.86398,1.89866 -5.35797,1.90159 l -1.68225,0.002 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path510" d="m 420.36151,481.93505 v -34.75712 l 1.92371,0.19854 c 2.49155,0.25715 4.263,1.11778 5.41822,2.63234 1.41345,1.85314 1.85463,7.51526 2.10513,27.01756 0.17647,13.73942 0.10561,18.07268 -0.42766,26.14973 -0.46732,7.07821 -0.78975,9.98262 -1.19916,10.80185 -0.79619,1.59315 -3.17954,2.71422 -5.77033,2.71422 h -2.04991 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path512" d="m 447.5015,906.00098 c -1.8715,-0.70661 -2.9819,-1.7154 -3.3712,-3.06268 -0.2644,-0.9154 -0.3472,-22.05223 -0.2745,-70.13291 l 0.1041,-68.8226 1.2946,-1.18645 c 2.041,-1.87038 4.9744,-2.37787 9.1933,-1.59049 4.2243,0.78838 8.8238,4.07342 10.363,7.40147 0.6902,1.49247 0.7677,2.40752 0.9325,11.01292 l 0.1796,9.38522 1.7041,5.81417 c 7.6872,26.22849 7.7031,50.97284 0.05,77.62707 l -1.8918,6.58875 -0.1107,9.17132 -0.1107,9.17132 -1.0625,1.92041 c -1.2599,2.27718 -3.7071,4.33173 -6.8926,5.78647 -1.902,0.86861 -2.8591,1.06811 -5.6666,1.18115 -2.0013,0.0806 -3.8109,-0.0275 -4.4404,-0.26514 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path514" d="m 441.6385,852.73071 c -0.5999,-0.72278 -2.3597,-1.63125 -3.6993,-1.9097 l -1.06248,-0.22083 -0.092,-16.88205 -0.092,-16.88205 1.50858,-0.39612 c 0.8297,-0.21787 2.1062,-0.86942 2.8367,-1.4479 l 1.3281,-1.05178 v 19.67251 c 0,10.81988 -0.06,19.67251 -0.1337,19.67251 -0.074,0 -0.3409,-0.24956 -0.594,-0.55459 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path516" d="m 420.05417,833.61702 v -43.39693 l 0.79594,0.42597 c 0.43776,0.23429 1.60747,1.27059 2.59935,2.30289 4.51391,4.69789 9.10684,12.69355 10.93014,19.02792 l 0.9034,3.1385 v 18.51411 18.51411 l -0.90522,3.13851 c -1.92215,6.6643 -6.56913,14.65718 -11.23693,19.32767 -1.32154,1.3223 -2.55667,2.40418 -2.74474,2.40418 -0.21796,0 -0.34194,-15.73501 -0.34194,-43.39693 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path524" d="m 313.99198,1292.8085 c -0.96622,-0.2545 -2.10487,-0.9559 -3.09247,-1.3094 -1.70548,-0.6104 -3.38805,-1.3678 -5.04339,-2.0839 -13.35521,-5.7781 -24.71137,-15.7518 -30.37881,-29.3689 l -5.07081,-12.1835 0.21567,-447.85593 -1.68502,-452.83955 5.21819,-6.82435 c 6.70736,-8.77188 19.17143,-19.4178 30.32839,-25.75165 12.83574,-7.28691 20.41017,-6.77706 55.40112,-6.27587 29.89918,0.42825 32.28987,-0.2527 38.18687,2.89292 7.63586,4.07316 15.0438,13.06457 18.54681,20.55351 0.66444,1.42047 1.68556,3.4563 2.05056,13.27608 1.04826,28.20251 0.44492,121.62908 -0.18564,457.03992 l -0.066,459.79922 -0.81036,6.3982 -3.45262,8.1963 c -1.76025,4.1787 -8.98897,10.0118 -12.10386,12.1705 -10.15801,7.0395 -14.51748,6.4392 -48.74484,6.3559 -20.03132,-0.049 -28.55486,0.083 -34.44933,-1.0022 -1.84725,-0.34 1.41291,0.4661 -0.16387,0.051 z m 78.87474,-99.2762 3.27873,-3.0802 v -65.5066 l -0.2424,-215.7738 0.25427,-68.97059 0.0331,-61.49435 c 0.11334,-210.56388 -0.50479,-313.30624 -0.8914,-364.08471 -0.35613,-46.77635 -0.40721,-49.50115 -1.95288,-50.80192 l -2.99002,-2.51629 -44.14324,-1.50348 -43.58958,0.51399 -4.70273,2.60905 -3.53443,3.53443 v 412.25021 412.25016 l 2.86193,2.7659 c 2.93271,2.8342 4.77438,2.8884 47.72015,2.8884 43.86243,0 44.67543,-0.052 47.8985,-3.0802 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path526" d="m 264.23721,492.50948 c -4.04844,-8.33293 -16.624,-23.7182 -35.08385,-43.12156 -26.81029,-28.1806 -38.94038,-44.27168 -38.0073,-50.84946 0.2392,-1.68623 1.46532,-4.24344 5.12049,-5.01886 3.19131,-0.67702 8.11058,0.35187 17.45091,-0.0198 23.39935,-0.93118 25.92443,-0.22204 34.18969,-9.37069 2.82569,-3.12771 9.72884,-13.68396 13.55981,-21.88811 2.0257,-4.33811 4.05045,-8.45316 5.51052,-10.90389 0.76226,-1.27947 1.07024,-2.31363 1.47031,-2.76411 0.28284,-0.31849 0.76027,-0.22269 0.8214,-0.25623 1.85097,-1.01578 0.12781,12.83353 -0.1142,27.83216 l 0.24214,24.66349 -0.68216,2.60676 h -3.52801 c -5.21935,0 -7.63511,7.05409 -7.62545,22.26651 0.0108,17.00318 1.77689,22.92697 7.15611,24.00281 l 4.16908,0.83382 v 23.90572 c 0,13.14815 0.49174,29.00863 0.25743,29.00863 -0.23432,0 -3.28323,-7.58512 -4.90692,-10.92716 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path528" d="m 295.1401,1185.4149 c -3.06937,-3.2672 5.67849,-7.7931 8.85227,-71.9607 l 3.14349,-63.5553 0.59066,-4.8296 c 0.52648,-4.3049 8.30627,-3.402 38.30164,-3.402 25.86749,0 38.24755,-2.2189 38.03519,0.9698 l 3.45868,11.3714 -2.79167,59.5757 3.06297,66.1632 -6.74309,5.9725 c -2.39371,2.1201 -8.12035,2.5912 -34.16751,2.5912 -30.89856,0 -48.7031,0.3392 -51.74263,-2.8962 z m 60.60873,-26.4444 c 6.3449,-10.045 11.38379,-15.7341 11.38379,-16.2306 0,-0.4966 -8.67254,-0.2057 -22.30766,-0.2057 -13.63512,0 -20.98513,-0.1734 -20.98513,0.1875 0,1.9194 20.33259,34.7155 21.23584,34.1572 0.58838,-0.3636 4.32826,-7.8634 10.67316,-17.9084 z m 1.57196,-45.1746 c 6.02548,-9.6095 10.68997,-15.7918 10.34635,-16.1355 -0.34362,-0.3436 -10.16328,-1.4002 -23.54772,-1.1865 l -22.58982,0.6608 12.33804,18.1627 c 12.12402,17.8476 11.33234,16.5866 12.68919,15.1005 0.93353,-1.0226 4.73849,-6.9926 10.76396,-16.602 z m -4.74836,-38.5533 c 6.72239,-10.6062 12.20345,-20.4597 11.88264,-20.7805 -0.32082,-0.3208 -6.79848,0.016 -20.13412,-0.1191 l -20.97842,-0.2121 10.503,17.5628 c 6.49171,10.8554 11.17262,15.0769 11.09751,17.0875 -0.008,0.2094 0.90699,-2.9325 7.62939,-13.5386 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path530" d="m 195.38552,386.2328 c -4.58371,-5.30681 -4.27509,-6.14052 -4.27509,-19.98524 0,-17.24523 1.72279,-19.61607 15.05755,-21.23724 9.67784,-1.17658 22.06465,-2.66101 54.5917,-14.7228 13.93049,-5.16576 29.54685,-8.05337 29.95931,-7.6409 0.41247,0.41246 -7.82477,7.64243 -12.70328,12.40148 -7.11384,6.93963 -10.0361,11.45679 -15.83597,23.5081 -9.7373,20.23271 -12.31671,25.43301 -19.9502,29.92064 -5.8988,3.46784 -9.64568,4.83664 -24.46127,4.50485 l -16.87996,-0.37801 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path532" d="m 260.25826,445.73518 c -0.87612,-2.14266 -2.24387,-11.42662 -2.30953,-18.43896 -0.0789,-8.42481 0.5889,-15.94359 2.95394,-19.86196 1.46407,-2.42565 4.20484,-2.8223 5.93526,-3.15555 0.81862,-0.15765 2.20028,-0.94768 2.77122,0.7176 1.00427,2.92917 0.90932,10.69905 0.90932,23.15575 0,20.49599 0.29677,21.57233 -2.45639,21.57233 -1.7985,0 -6.80502,-1.5465 -7.80382,-3.98921 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path534" d="m 335.78812,307.06698 c 0,-1.77848 0.75861,-5.19179 4.31531,-6.11265 4.01911,-1.04059 12.44741,0.017 24.70426,0.21676 11.74082,0.19135 18.48536,-0.47698 21.97918,0.38297 2.88441,0.70995 3.12648,3.58747 3.31976,4.59386 0.43963,2.28916 -2.61413,0.94 -26.90979,0.94 -14.47139,0 -27.40872,0.6628 -27.40872,-0.0209 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path536" d="m 424.74041,404.13845 c 8.8e-4,-3.58112 0.0807,-4.98041 0.17728,-3.10952 0.0966,1.87089 0.0959,4.8009 -0.002,6.51113 -0.0975,1.71024 -0.17656,0.17952 -0.17569,-3.40161 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path538" d="m 420.0381,404.10822 v -6.7918 l 1.87821,0.15545 1.87822,0.15545 0.14568,5.50942 c 0.1916,7.24582 0.0477,7.76327 -2.15865,7.76327 h -1.74346 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path548" d="m 334.02423,1070.9922 -10.6817,-16.8613 10.97722,-0.1953 c 6.03746,-0.1074 15.72027,-0.1074 21.51734,0 l 10.54013,0.1953 -10.29748,16.2913 c -5.66361,8.9602 -10.53965,16.5478 -10.83564,16.8613 -0.296,0.3136 -5.34494,-7.0175 -11.21987,-16.2913 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path550" d="m 334.02948,1115.1625 -10.82491,-17.1159 11.04619,-0.1953 c 6.07541,-0.1074 15.82454,-0.1074 21.66473,0 l 10.61853,0.1953 -10.74364,16.9996 c -5.90901,9.3498 -10.78693,17.052 -10.83982,17.1159 -0.0529,0.064 -4.96738,-7.5858 -10.92108,-16.9996 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path552" d="m 334.13106,1159.4901 -10.61146,-16.8195 10.88868,-0.1953 c 5.98878,-0.1074 15.60026,-0.1074 21.35885,0 l 10.47016,0.1953 -10.39596,16.468 c -5.71779,9.0575 -10.55411,16.6262 -10.74739,16.8195 -0.19329,0.1933 -5.12658,-7.2173 -10.96288,-16.468 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path572" d="m 420.0231,1016.5918 c 0,-20.55693 0.0782,-24.48013 0.48787,-24.48013 1.26302,0 1.28964,0.54348 1.19693,24.43313 l -0.0911,23.4691 -0.79685,0.529 -0.79686,0.5291 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#1a1a1a;stroke-width:.25;stroke-opacity:1" id="path987" d="m 336.33885,1011.7736 c -0.4903,-0.1025 -1.34011,-0.499 -1.86387,-0.5891 -2.10906,-0.3631 -4.24247,-1.0485 -6.03886,-2.8281 -2.21068,-2.1901 -2.45772,-4.2576 -2.92495,-7.2201 -0.0644,-0.4083 -0.33547,-3.32902 -0.7219,-7.96551 -0.47191,-5.66195 -0.26588,-14.13412 -0.22086,-24.07743 l 0.13273,-29.31033 2.1854,-3.07209 c 1.68451,-2.36796 2.85286,-4.8002 5.70807,-6.16483 3.14456,-1.50292 4.3061,-1.05628 13.1741,-0.94462 7.32026,0.0922 8.2212,0.0618 9.5738,0.56462 4.38444,1.62985 7.57683,5.059 8.6811,9.18385 0.22909,0.85573 0.41962,8.86488 0.21397,32.35897 l -0.056,30.50887 -0.83085,2.4841 c -0.94256,2.8179 -3.22521,4.2492 -5.91157,5.5336 -1.13944,0.5447 -2.59573,1.1447 -3.33637,1.2835 -1.10922,0.2079 -5.88727,0.4361 -10.04355,0.3913 -2.3498,-0.025 -3.61164,0.2383 -5.14351,0.029 -0.87269,-0.1194 -0.99665,0.165 -1.3228,0.097 z m 13.30469,-23.7451 c 2.76719,-0.58714 4.69699,-2.04661 5.74377,-4.34391 0.47551,-1.04356 0.57052,-1.68351 0.57531,-3.875 0.009,-4.20728 -1.02802,-6.30701 -3.78078,-7.65381 -2.39779,-1.17313 -5.79519,-0.86226 -7.69553,0.70416 -1.16483,0.96015 -1.85705,2.35288 -3.009,6.05403 -1.00853,3.24035 -1.41582,4.0427 -2.17437,4.28345 -1.5805,0.50163 -2.90029,-1.36574 -2.62256,-3.71068 0.19465,-1.64357 0.66036,-2.28932 2.02759,-2.81147 1.12124,-0.4282 1.13535,-0.44797 1.13263,-1.58714 -0.002,-0.63445 -0.0725,-1.57541 -0.15771,-2.09104 -0.13433,-0.81269 -0.24453,-0.9375 -0.82772,-0.9375 -2.30578,0 -4.85058,1.92056 -5.66126,4.27257 -0.69366,2.01248 -0.63686,5.68454 0.11372,7.35243 1.14973,2.55483 2.92227,3.72494 5.66589,3.74023 1.40395,0.008 2.00379,-0.11802 2.99769,-0.62888 1.9043,-0.97879 2.69476,-2.2324 3.99147,-6.3301 1.20414,-3.80517 1.74731,-4.65625 2.9717,-4.65625 0.97546,0 2.09342,0.64567 2.49633,1.44174 1.35565,2.67848 0.17187,5.70204 -2.55195,6.51812 -0.93521,0.2802 -1.0352,0.38787 -1.03324,1.11268 0.003,0.96835 0.28627,3.42746 0.39535,3.42746 0.0428,0 0.67403,-0.12649 1.40267,-0.28109 z m 5.94981,-29.21891 v -7.5 h -2 -2 v 5.25 5.25 h -9.25 -9.25 v 2.25 2.25 h 11.25 11.25 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path504" d="m 300.85,1194.9934 c -1.71731,-0.8472 -4.91972,-2.1462 -5.54391,-3.5161 -0.83944,-1.8424 0.86542,-110.6107 0.86542,-412.9166 0,-355.43486 -2.26943,-409.5887 -1.00378,-412.03621 2.62275,-5.07184 6.80299,-6.80795 52.50153,-5.38304 l 40.5665,0.52575 3.70004,2.69699 2.40356,3.70288 v 409.59752 c 0,267.41961 0.6532,377.35501 0.22653,405.85801 -0.0462,3.0834 0.15924,4.3842 0.0303,5.658 -0.0851,0.8402 -0.5067,2.1372 -0.56245,2.2596 -2.45684,5.3924 -4.14164,3.9318 -48.47815,3.9071 -34.72063,-0.019 -42.05298,0.9547 -44.70561,-0.3539 z m 80.27252,-10.4604 c 2.12921,-1.989 3.21222,-4.1353 3.6646,-7.2624 0.35319,-2.4415 0.50577,-32.4911 0.33906,-66.777 l -0.30309,-62.3379 -1.817,-4.7667 -4.72991,-1.7818 -30.78478,-0.3127 c -34.35748,-0.3489 -37.22985,0.016 -40.34521,5.1254 -1.88189,3.0863 -1.95191,5.545 -1.95552,68.6629 l -0.004,65.4619 3.40582,3.4058 3.40582,3.4059 h 33.05076 33.05075 z m -22.91983,-173.0609 c 1.57682,-0.8154 3.84958,-2.6835 5.00011,-4.1461 2.02772,-2.5779 2.08689,-3.5907 2.08689,-36.43981 l -0.69949,-33.99855 -2.38805,-3.40626 c -3.72994,-4.24816 -8.21239,-5.25265 -18.24178,-5.26006 -5.84642,-0.004 -8.30481,0.20024 -11.76537,1.9453 -7.84443,3.95572 -7.97242,4.60298 -7.97242,40.31894 0,34.66614 0.41247,35.72854 7.12185,40.21074 2.99392,2.0001 4.44288,2.362 13.60803,2.362 7.24014,0 11.25811,-0.556 13.25023,-1.5862 z m -5.95573,-138.90396 c 6.10086,-3.11739 8.53502,-6.75988 8.53502,-12.77184 0,-8.4223 -5.95352,-14.17655 -15.26265,-14.7518 -7.02351,-0.43401 -12.57208,2.34255 -15.43573,7.72419 -7.14597,13.42935 8.05461,27.00867 22.16336,19.79945 z m 1.45148,-63.42988 c 1.10087,-1.10086 1.57412,-3.48865 1.57412,-7.94215 0,-8.51585 -1.07862,-9.51627 -10.26023,-9.51627 -9.38389,0 -10.77573,1.20668 -10.77573,9.34222 0,8.48897 1.31434,9.69032 10.60168,9.69032 5.28806,0 7.7177,-0.43166 8.86016,-1.57412 z m 0.37207,-38.69473 c 0.69725,-0.69725 1.20205,-4.03875 1.20205,-7.9569 0,-8.44376 -1.52314,-9.87359 -10.51798,-9.87359 -8.88853,0 -10.51798,1.47199 -10.51798,9.50153 0,8.65087 1.00564,9.53101 10.89005,9.53101 4.68578,0 8.21631,-0.4745 8.94386,-1.20205 z m -0.62982,-39.52257 c 2.44013,-2.20828 2.62327,-13.43508 0.25775,-15.80059 -2.26592,-2.26593 -15.101,-2.20499 -17.62997,0.0837 -2.48085,2.24514 -2.59975,12.86248 -0.17405,15.54285 2.27669,2.51572 14.82125,2.64015 17.54627,0.17404 z m -0.1057,-38.44592 c 1.6168,-0.86529 1.93757,-2.13749 1.93757,-7.6844 0,-9.02878 -1.23743,-10.31119 -9.94949,-10.31119 -9.51513,0 -11.08647,1.3467 -11.08647,9.50153 0,8.51102 1.08671,9.53101 10.15453,9.53101 3.85346,0 7.8782,-0.46663 8.94386,-1.03695 z m 4.89747,-81.8069 c 5.473,-3.60783 6.98335,-3.06909 7.02174,-39.48044 0.0344,-32.65824 -0.45612,-33.68452 -2.485,-36.2638 -1.3225,-1.68128 -2.16617,-2.68325 -3.79664,-3.53269 -2.85079,-1.4852 -6.79655,-1.97333 -14.0201,-1.97333 -9.16515,0 -9.82283,0.81199 -12.81675,2.81203 -6.85365,4.57854 -7.27471,4.72625 -6.9653,40.5757 0.2612,30.26439 -0.11042,32.144 1.7811,34.65729 3.82743,5.08555 5.86745,5.85717 18.30393,5.87882 9.72787,0.0169 10.49635,-1.03831 12.97702,-2.67358 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.373293;stroke-opacity:1" id="path989" d="m 337.67662,692.88512 c -2.67305,-0.96309 -3.2939,-2.84605 -3.09019,-9.37193 0.17168,-5.49938 0.64108,-6.64523 3.20441,-7.82229 1.52187,-0.69884 2.42425,-0.79766 7.30307,-0.79982 6.75767,-0.003 7.98061,0.38279 9.09592,2.86921 0.61253,1.3655 0.72342,2.47625 0.73034,7.31525 0.007,5.38513 -0.0388,5.75973 -0.82685,6.67489 -0.62002,0.71994 -1.40826,1.06314 -3.06165,1.33297 -3.40014,0.55493 -11.60256,0.43314 -13.35505,-0.19828 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370491;stroke-opacity:1" id="path991" d="m 339.04414,731.97109 c -3.60561,-0.93726 -4.48264,-2.73045 -4.45483,-9.10842 0.0218,-5.00727 0.73904,-7.15345 2.73101,-8.17253 1.29271,-0.66135 2.19762,-0.74953 7.69168,-0.74953 8.49855,0 8.96303,0.26628 9.77396,5.60339 0.32491,2.13833 0.32915,3.61396 0.0172,5.9992 -0.53103,4.06091 -1.10757,5.18233 -3.09269,6.01548 -2.09206,0.87802 -9.89752,1.13216 -12.66637,0.41241 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.365528;stroke-opacity:1" id="path993" d="m 337.75825,770.7391 c -2.54567,-0.94315 -3.11216,-2.48804 -3.09149,-8.43076 0.028,-8.05586 1.30547,-9.15871 10.57454,-9.12914 4.14079,0.0132 5.1614,0.13044 6.36851,0.73158 2.63337,1.31141 2.92902,2.08079 3.06977,7.98827 0.13827,5.8041 -0.24296,8.00904 -1.50624,8.71158 -1.28401,0.71409 -13.55834,0.81639 -15.41509,0.12847 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370789;stroke-opacity:1" id="path995" d="m 340.25178,810.31175 c -2.30728,-0.35082 -4.07035,-1.26307 -4.79602,-2.48153 -0.63065,-1.05893 -0.72313,-1.90705 -0.72313,-6.63222 0,-8.75452 0.4422,-9.15459 10.11842,-9.15459 9.55452,0 9.93447,0.34222 9.93447,8.94819 0,8.55026 -0.56098,9.15949 -8.62352,9.3653 -2.64352,0.0675 -5.30312,0.0472 -5.91022,-0.0451 z"/><path id="path4136" d="m 620.05176,101.33936 h -13.19009 l -0.0372,-8.25531 h -14.10678 c -3.694,0 -4.86707,3.29254 -4.86707,8.2606 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 606.85329,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 678.37103,56.29539 v 15.94604 h -43.5888 V 56.01064 c 0,-2.09826 1.87258,-3.04523 3.55963,-3.4883 12.17302,-3.19604 25.27663,-3.03408 36.83267,0 1.82189,0.47838 3.1965,1.67683 3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 720.40437,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 724.94622,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 741.03641,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 643.93309,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 746.85546,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 870.42561,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 797.67583,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 907.97933,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.47833 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.59359 -7.55529,-7.40352 -26.96999,-35.0496 -56.25473,-53.08707 -86.3059,-65.49263 h -63.63968 c -27.37307,12.02627 -42.63451,29.98675 -54.6313,49.5466 V 61.9055 c 0,4.46695 -3.77561,9.11203 -8.71777,9.11203 h -52.88777 v 128.70726 z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 898.96304,95.57843 H 671.57211 c 0.11854,-46.39485 23.40196,-94.42781 68.1792,-94.42781 l 63.60853,0.74648 c 62.27359,11.13309 75.07205,54.96226 95.6032,93.68133 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 917.62642,126.18349 H 669.66769 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 754.52313,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 763.60822,52.91602 V 42.51329 l 5.50031,0.0182 c 5.86555,0.0182 5.99551,0.0235 7.21251,0.23684 0.72764,0.12779 1.2063,0.27395 1.73262,0.5297 0.56119,0.27264 0.92919,0.53686 1.3444,0.96517 0.6865,0.70821 1.17119,1.61242 1.4232,2.65506 0.10465,0.43649 0.11392,0.54629 0.11623,1.4018 6.9e-4,0.72536 -0.0233,1.00826 -0.0743,1.29452 -0.49307,2.37268 -2.15713,3.86338 -4.92053,4.40866 -0.52052,0.10275 -0.58004,0.12279 -0.5089,0.17313 0.044,0.0312 0.27805,0.18384 0.51935,0.33899 1.26535,0.81414 2.04879,1.63119 3.24347,3.38328 0.43519,0.6382 3.38993,5.24266 3.43201,5.34806 0.0233,0.0423 -0.49075,0.051 -2.51118,0.0421 l -2.53257,-0.0114 -1.89628,-2.76629 c -2.70088,-3.93961 -3.00426,-4.35632 -3.57776,-4.91249 -0.79112,-0.76705 -1.35952,-0.94266 -3.17329,-0.98035 l -1.06565,-0.0228 v 4.3512 4.35117 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.66304 c 0.70021,-0.0758 1.02521,-0.15376 1.4046,-0.337 0.60955,-0.2945 1.03662,-0.84304 1.20307,-1.54567 0.0907,-0.37929 0.0884,-1.17286 -0.002,-1.51464 -0.27525,-1.03723 -1.09727,-1.6771 -2.30428,-1.79364 -0.22549,-0.0228 -1.74122,-0.0399 -3.36922,-0.0406 l -2.96011,-0.002 v 2.66306 2.66304 l 2.78783,-0.0228 c 1.66078,-0.0137 2.97079,-0.0419 3.23998,-0.0711 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 743.58665,61.4392 v -1.87954 l 5.57588,-6.74897 c 3.06678,-3.71194 5.57589,-6.75827 5.57589,-6.76966 0,-0.0114 -2.22827,-0.0205 -4.95147,-0.0205 h -4.95146 v -1.75092 -1.75094 h 7.7716 7.77183 v 1.61419 1.61418 l -5.83789,7.04557 -5.83763,7.04554 6.05291,0.0114 6.05316,0.0114 v 1.7297 1.72968 h -8.6113 -8.61152 v -1.87951 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path141" d="m 337.37689,564.16039 c 0.004,-3.45814 0.214,-4.28994 1.21089,-4.80544 1.18361,-0.61208 3.0461,-0.20122 3.8108,0.84064 0.33284,0.45348 0.37167,0.7949 0.42717,3.75651 l 0.0611,3.25769 h -2.7569 -2.7569 z"/></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg b/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg
new file mode 100644
index 00000000..f5380f3a
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns:svg="http://www.w3.org/2000/svg"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1050 1050.5"
+	 style="enable-background:new 0 0 1050 1050.5;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#20221F;}
+	.st1{fill:#3B3B3B;}
+	.st2{fill:#121212;}
+	.st3{fill:#444542;}
+	.st4{fill:#FFFFFF;}
+	.st5{fill:#444542;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
+	.st6{fill:#454644;}
+	.st7{fill:#454644;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
+	.st8{fill:#3B3C3A;}
+	.st9{font-family:'Helvetica-Bold';}
+	.st10{font-size:40px;}
+	.st11{fill:#0D0D0A;}
+</style>
+<g id="Front">
+	<path id="Right_Grip_00000028282943321285403220000008369785803052272051_" class="st0" d="M766,850.5
+		c34,28.2,27.6,35.9,68.5,108.5c36.7,74.7,64.4,104.4,125.1,84.1v0c95.3-57.9,59.3-145.3,43.6-275.2c-10-60.6-35.6-190.3-35.6-190.3
+		L766,850.5z"/>
+	<path id="Left_Grip" class="st0" d="M82.3,577.6c0,0-25.6,129.7-35.6,190.3C31,897.8-5,985.1,90.3,1043v0
+		c60.8,20.3,88.4-9.4,125.1-84.1c40.9-72.7,34.5-80.3,68.5-108.5L82.3,577.6z"/>
+	<path id="Right_Bumper_00000006710349871522532470000011078040965381267594_" class="st1" d="M676.3,378.4
+		c10.1-4.3,39.7-22.5,58.7-19.7c59.5,0.9,166.7,17.7,172.6,81.2"/>
+	<path id="Left_Bumper_00000024680414077879639570000011759596763560342154_" class="st1" d="M142.4,439.9
+		c5.9-63.4,113-80.2,172.6-81.2c19-2.8,48.6,15.4,58.7,19.7"/>
+	<path id="Background_00000141418846164053065470000016150094984198570163_" class="st2" d="M766,850.5
+		c35.5-30.8,68.5-74.7,96-113.5c26.9-36.3,94.7-136.7,105.6-159.3c0-2.4-6.3-30.1-12.8-56.2C919.1,361.9,702.2,378.1,525,378.1
+		c-177.4,0-394.1-16.2-429.9,143.3c-6.5,26-12.8,53.8-12.8,56.2c10.9,22.6,78.8,123,105.6,159.3c27.5,38.8,60.5,82.8,96,113.5"/>
+	<g id="Directional_Pad">
+		<path id="Background_00000032628022449190479560000015279211462520783249_" class="st3" d="M466.2,683.5h-40c-2.8,0-5-2.2-5-5v-40
+			c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40
+			c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30C471.2,685.8,469,683.5,466.2,683.5z"/>
+		<g id="Arrows">
+			<g>
+				<polygon class="st4" points="393.7,746 408.7,746 401.2,761 				"/>
+			</g>
+			<g>
+				<polygon class="st4" points="358.7,696 358.7,711 343.7,703.5 				"/>
+			</g>
+			<g>
+				<polygon class="st4" points="408.7,661 393.7,661 401.2,646 				"/>
+			</g>
+			<g>
+				<polygon class="st4" points="443.7,711 443.7,696 458.7,703.5 				"/>
+			</g>
+		</g>
+	</g>
+	<g id="R_Thumbstick_00000152226188525111835500000011838297421350334865_">
+		<circle id="Background_00000035532849542660068350000006517224202948159422_" class="st0" cx="650.6" cy="703.5" r="55"/>
+		<circle id="Stick" class="st5" cx="650.6" cy="703.5" r="45"/>
+	</g>
+	<g id="L_Thumbstick_00000047032468231999382210000005512347386782594484_">
+		<circle id="Background_00000182502673988292164000000007125719133096369561_" class="st0" cx="240.2" cy="564.8" r="55"/>
+		<circle id="Stick_00000075121990265259598900000000214370239054002365_" class="st5" cx="240.2" cy="564.8" r="45"/>
+	</g>
+	<g id="Minus_Button">
+		<circle id="_Background_00000120554951013892796430000015877571645746699662_" class="st6" cx="401" cy="489.3" r="22.5"/>
+		<polyline id="Plus_00000039131319101621183460000006196023733899658629_" class="st4" points="386.2,491.8 386.2,486.8 
+			416.2,486.8 416.2,491.8 		"/>
+	</g>
+	<g id="Plus_Button">
+		<circle id="_Background" class="st6" cx="650.4" cy="489.6" r="22.5"/>
+		<polygon id="Plus" class="st4" points="665.6,487.1 653.1,487.1 653.1,474.4 648.1,474.4 648.1,487.1 635.6,487.1 635.6,492.1 
+			648.1,492.1 648.1,504.4 653.1,504.4 653.1,492.1 665.6,492.1 		"/>
+	</g>
+	<g id="Home_Button_00000029758737660217614780000001403165237001195407_">
+		<circle id="_Background_00000132788487854287834010000009548421243227981499_" class="st6" cx="605.4" cy="564.8" r="22.5"/>
+		<path id="Home" class="st4" d="M605.4,549.8l-15,15h5v15h20v-15h5L605.4,549.8z M610.4,574.8h-10v-10h10V574.8z"/>
+	</g>
+	<g id="Capture_Button_00000105394663133565750060000017455731898661404072_">
+		<path class="st6" d="M468.6,586.5h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5
+			C473.6,584.2,471.4,586.5,468.6,586.5z"/>
+		<circle class="st7" cx="453.6" cy="566.7" r="15"/>
+	</g>
+	<g id="Buttons_00000023239109225132251950000005218343074279628213_">
+		<g id="A_Button">
+			<circle id="Background_00000006699118933065716380000004636085088820886913_" class="st8" cx="863.9" cy="564.8" r="35"/>
+			<text transform="matrix(1 0 0 1 849.4224 578.6607)" class="st4 st9 st10">A</text>
+		</g>
+		<g id="X_Button">
+			<circle id="Background_00000083074713085756701790000016893839312974798515_" class="st8" cx="793.9" cy="494.8" r="35"/>
+			<text transform="matrix(1 0 0 1 780.5266 508.6604)" class="st4 st9 st10">X</text>
+		</g>
+		<g id="Y_Button_00000100344340438574137780000014238704828967683973_">
+			<circle id="Background_00000137100455694543496620000011124722786613194377_" class="st8" cx="723.9" cy="564.8" r="35"/>
+			<text transform="matrix(1 0 0 1 710.5263 578.661)" class="st4 st9 st10">Y</text>
+		</g>
+		<g id="B_Button_00000041994261956088037220000013468634544777304733_">
+			<circle id="Background_00000096038108578846046800000001873940014252420514_" class="st8" cx="793.9" cy="634.8" r="35"/>
+			<text transform="matrix(1 0 0 1 780.9706 648.6605)" class="st4 st9 st10">B</text>
+		</g>
+	</g>
+</g>
+<g id="Top_Down">
+	<path id="Left_Grip_00000026131988385328425370000016677941743356253314_" class="st0" d="M219.2,78.5
+		c-12.5-17.6-25.9-42.3-45.6-58.6C153.5,3.3,112.1-4.7,87.1,5.8c-13.9,5.8-33.4,33.1-42.7,52.8C33.9,80.9,30.4,109.9,32,141.4
+		c1.2,25.1,5.3,51.7,14.2,78.6c0,0,14.3,53.8,42.8,80.8c11.2,10.6,35,26.6,35,26.6l116-217.5C240,109.9,224.6,86.2,219.2,78.5z"/>
+	<path id="Right_Grip_00000016782759094708820330000002450847065936193693_" class="st0" d="M828.6,78.5
+		c12.5-17.6,25.9-42.3,45.6-58.6c20.1-16.6,61.4-24.5,86.5-14.1c13.9,5.8,33.4,33.1,42.7,52.8c10.5,22.3,13.9,51.3,12.4,82.8
+		c-1.2,25.1-5.3,51.7-14.2,78.6c0,0-14.3,53.8-42.8,80.8c-11.2,10.6-35,26.6-35,26.6l-116-217.5C807.8,109.9,823.2,86.2,828.6,78.5z
+		"/>
+	<path id="Background_00000169534857628063347190000007586592143875928969_" class="st11" d="M866,122.2
+		c66.3,18.7,85.1,128.8,69,186c-2.5,54.2-148.9,15.3-265.1,31.2c-41.1,1.7-91.8,2.4-145.9,2.3c-54.1,0-104.8-0.6-145.9-2.3
+		c-116.2-15.9-262.6,23.1-265.1-31.2c-16.1-57.1,2.6-167.3,69-186l60.5-18.8l38.9-1.9c40.2,0.1,142.8,0,242.7,0
+		c99.9,0,202.4,0.1,242.7,0l38.9,1.9L866,122.2z"/>
+	<g id="ZL_Trigger_00000005254517714433203260000014117442438696169895_">
+		<path id="Background_00000111870097528015387240000017384507710402295183_" class="st1" d="M145.9,239.2
+			c15.2-97.4,38.1-147.2,141.7-137c8.2,16.4,43.3,83,50.6,105.7C280.6,227.2,204.7,225.6,145.9,239.2z"/>
+		<text id="ZL_Trigger" transform="matrix(1.0139 0 0 1 218.3906 179.3992)" class="st4 st9 st10">ZL</text>
+	</g>
+	<g id="ZR_Trigger">
+		<path id="Background_00000133526766189752063450000016781240006605114763_" class="st1" d="M716.2,207.9
+			c7.4-22.7,42.5-89.3,50.6-105.7c103.7-10.2,126.5,39.6,141.7,137C849.8,225.6,773.8,227.2,716.2,207.9z"/>
+		
+			<text id="ZL_Trigger_00000000206350378518266660000001315160307759857328_" transform="matrix(1.0139 0 0 1 784.2356 179.3992)" class="st4 st9 st10">ZR</text>
+	</g>
+	<g id="R_Trigger_00000085939413106284991650000014018840000393673094_">
+		<path id="Background" class="st1" d="M664,318.5c7-10.1,27.8-78.4,45.4-78.7C1040.8,243.7,897.1,334,664,318.5z"/>
+		<text id="R_Trigger" transform="matrix(1 0 0 1 769.6461 292.8947)" class="st4 st9 st10">R</text>
+	</g>
+	<g id="L_Trigger">
+		<path id="Background_00000043427985111927735300000011910735497762731703_" class="st1" d="M340.6,238.6
+			c17.6,0.3,38.4,68.6,45.4,78.7C152.9,332.8,9.2,242.6,340.6,238.6z"/>
+		
+			<text id="R_Trigger_00000092444210070373642420000009814634285137007748_" transform="matrix(1 0 0 1 253.7327 291.7279)" class="st4 st9 st10">L</text>
+	</g>
+</g>
+</svg>
diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NCA.png b/src/Ryujinx.UI.Common/Resources/Icon_NCA.png
new file mode 100644
index 00000000..feae77b9
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_NCA.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NRO.png b/src/Ryujinx.UI.Common/Resources/Icon_NRO.png
new file mode 100644
index 00000000..3a9da621
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_NRO.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NSO.png b/src/Ryujinx.UI.Common/Resources/Icon_NSO.png
new file mode 100644
index 00000000..16de84be
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_NSO.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NSP.png b/src/Ryujinx.UI.Common/Resources/Icon_NSP.png
new file mode 100644
index 00000000..4f98e22e
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_NSP.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Icon_XCI.png b/src/Ryujinx.UI.Common/Resources/Icon_XCI.png
new file mode 100644
index 00000000..f9c34f47
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_XCI.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png b/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png
new file mode 100644
index 00000000..cbee8037
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png
new file mode 100644
index 00000000..baececa9
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png
new file mode 100644
index 00000000..25fc892d
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png
new file mode 100644
index 00000000..50b81752
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png
new file mode 100644
index 00000000..95bc742b
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png
new file mode 100644
index 00000000..9a521e3f
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png
new file mode 100644
index 00000000..44da0ac4
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png b/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png
new file mode 100644
index 00000000..0e8da15e
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png
new file mode 100644
index 00000000..66962e7d
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png differ
diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png
new file mode 100644
index 00000000..040ca169
Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png differ
diff --git a/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj
new file mode 100644
index 00000000..387e998b
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj
@@ -0,0 +1,68 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Remove="Resources\Controller_JoyConLeft.svg" />
+    <None Remove="Resources\Controller_JoyConPair.svg" />
+    <None Remove="Resources\Controller_JoyConRight.svg" />
+    <None Remove="Resources\Controller_ProCon.svg" />
+    <None Remove="Resources\Icon_NCA.png" />
+    <None Remove="Resources\Icon_NRO.png" />
+    <None Remove="Resources\Icon_NSO.png" />
+    <None Remove="Resources\Icon_NSP.png" />
+    <None Remove="Resources\Icon_XCI.png" />
+    <None Remove="Resources\Logo_Amiibo.png" />
+    <None Remove="Resources\Logo_Discord.png" />
+    <None Remove="Resources\Logo_GitHub.png" />
+    <None Remove="Resources\Logo_Patreon.png" />
+    <None Remove="Resources\Logo_Ryujinx.png" />
+    <None Remove="Resources\Logo_Twitter.png" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Include="Resources\Controller_JoyConLeft.svg" />
+    <EmbeddedResource Include="Resources\Controller_JoyConPair.svg" />
+    <EmbeddedResource Include="Resources\Controller_JoyConRight.svg" />
+    <EmbeddedResource Include="Resources\Controller_ProCon.svg" />
+    <EmbeddedResource Include="Resources\Icon_NCA.png" />
+    <EmbeddedResource Include="Resources\Icon_NRO.png" />
+    <EmbeddedResource Include="Resources\Icon_NSO.png" />
+    <EmbeddedResource Include="Resources\Icon_NSP.png" />
+    <EmbeddedResource Include="Resources\Icon_XCI.png" />
+    <EmbeddedResource Include="Resources\Logo_Amiibo.png" />
+    <EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
+    <EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
+    <EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
+    <EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
+    <EmbeddedResource Include="Resources\Logo_GitHub_Light.png" />
+    <EmbeddedResource Include="Resources\Logo_Patreon_Dark.png" />
+    <EmbeddedResource Include="Resources\Logo_Patreon_Light.png" />
+    <EmbeddedResource Include="Resources\Logo_Twitter_Dark.png" />
+    <EmbeddedResource Include="Resources\Logo_Twitter_Light.png" />
+  </ItemGroup>
+
+  <ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''">
+    <EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
+  </ItemGroup>
+
+  <ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''">
+    <EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" />
+    <EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="DiscordRichPresence" />
+    <PackageReference Include="securifybv.ShellLink" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
+    <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
+    <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs
new file mode 100644
index 00000000..c7fe05a0
--- /dev/null
+++ b/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs
@@ -0,0 +1,85 @@
+using Ryujinx.Common.Logging;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.SystemInfo
+{
+    [SupportedOSPlatform("linux")]
+    class LinuxSystemInfo : SystemInfo
+    {
+        internal LinuxSystemInfo()
+        {
+            string cpuName = GetCpuidCpuName();
+
+            if (cpuName == null)
+            {
+                var cpuDict = new Dictionary<string, string>(StringComparer.Ordinal)
+                {
+                    ["model name"] = null,
+                    ["Processor"] = null,
+                    ["Hardware"] = null,
+                };
+
+                ParseKeyValues("/proc/cpuinfo", cpuDict);
+
+                cpuName = cpuDict["model name"] ?? cpuDict["Processor"] ?? cpuDict["Hardware"] ?? "Unknown";
+            }
+
+            var memDict = new Dictionary<string, string>(StringComparer.Ordinal)
+            {
+                ["MemTotal"] = null,
+                ["MemAvailable"] = null,
+            };
+
+            ParseKeyValues("/proc/meminfo", memDict);
+
+            // Entries are in KiB
+            ulong.TryParse(memDict["MemTotal"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong totalKiB);
+            ulong.TryParse(memDict["MemAvailable"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong availableKiB);
+
+            CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
+            RamTotal = totalKiB * 1024;
+            RamAvailable = availableKiB * 1024;
+        }
+
+        private static void ParseKeyValues(string filePath, Dictionary<string, string> itemDict)
+        {
+            if (!File.Exists(filePath))
+            {
+                Logger.Error?.Print(LogClass.Application, $"File \"{filePath}\" not found");
+
+                return;
+            }
+
+            int count = itemDict.Count;
+
+            using StreamReader file = new(filePath);
+
+            string line;
+            while ((line = file.ReadLine()) != null)
+            {
+                string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries);
+
+                if (kvPair.Length < 2)
+                {
+                    continue;
+                }
+
+                string key = kvPair[0];
+
+                if (itemDict.TryGetValue(key, out string value) && value == null)
+                {
+                    itemDict[key] = kvPair[1];
+
+                    if (--count <= 0)
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs
new file mode 100644
index 00000000..36deaf35
--- /dev/null
+++ b/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs
@@ -0,0 +1,164 @@
+using Ryujinx.Common.Logging;
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Text;
+
+namespace Ryujinx.UI.Common.SystemInfo
+{
+    [SupportedOSPlatform("macos")]
+    partial class MacOSSystemInfo : SystemInfo
+    {
+        internal MacOSSystemInfo()
+        {
+            if (SysctlByName("kern.osversion", out string buildRevision) != 0)
+            {
+                buildRevision = "Unknown Build";
+            }
+
+            OsDescription = $"macOS {Environment.OSVersion.Version} ({buildRevision}) ({RuntimeInformation.OSArchitecture})";
+
+            string cpuName = GetCpuidCpuName();
+
+            if (cpuName == null && SysctlByName("machdep.cpu.brand_string", out cpuName) != 0)
+            {
+                cpuName = "Unknown";
+            }
+
+            ulong totalRAM = 0;
+
+            if (SysctlByName("hw.memsize", ref totalRAM) != 0) // Bytes
+            {
+                totalRAM = 0;
+            }
+
+            CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
+            RamTotal = totalRAM;
+            RamAvailable = GetVMInfoAvailableMemory();
+        }
+
+        static ulong GetVMInfoAvailableMemory()
+        {
+            var port = mach_host_self();
+
+            uint pageSize = 0;
+            var result = host_page_size(port, ref pageSize);
+
+            if (result != 0)
+            {
+                Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_page_size() error = {result}");
+                return 0;
+            }
+
+            const int Flavor = 4; // HOST_VM_INFO64
+            uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
+            VMStatistics64 stats = new();
+            result = host_statistics64(port, Flavor, ref stats, ref count);
+
+            if (result != 0)
+            {
+                Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_statistics64() error = {result}");
+                return 0;
+            }
+
+            return (ulong)(stats.FreeCount + stats.InactiveCount) * pageSize;
+        }
+
+        private const string SystemLibraryName = "libSystem.dylib";
+
+        [LibraryImport(SystemLibraryName, SetLastError = true)]
+        private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
+
+        private static int SysctlByName(string name, IntPtr oldValue, ref ulong oldSize)
+        {
+            if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
+            {
+                int err = Marshal.GetLastWin32Error();
+
+                Logger.Error?.Print(LogClass.Application, $"Cannot retrieve '{name}'. Error Code {err}");
+
+                return err;
+            }
+
+            return 0;
+        }
+
+        private static int SysctlByName<T>(string name, ref T oldValue)
+        {
+            unsafe
+            {
+                ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
+
+                return SysctlByName(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
+            }
+        }
+
+        private static int SysctlByName(string name, out string oldValue)
+        {
+            oldValue = default;
+
+            ulong strSize = 0;
+
+            int res = SysctlByName(name, IntPtr.Zero, ref strSize);
+
+            if (res == 0)
+            {
+                byte[] rawData = new byte[strSize];
+
+                unsafe
+                {
+                    fixed (byte* rawDataPtr = rawData)
+                    {
+                        res = SysctlByName(name, (IntPtr)rawDataPtr, ref strSize);
+                    }
+
+                    if (res == 0)
+                    {
+                        oldValue = Encoding.ASCII.GetString(rawData);
+                    }
+                }
+            }
+
+            return res;
+        }
+
+        [LibraryImport(SystemLibraryName, SetLastError = true)]
+        private static partial uint mach_host_self();
+
+        [LibraryImport(SystemLibraryName, SetLastError = true)]
+        private static partial int host_page_size(uint host, ref uint out_page_size);
+
+        [StructLayout(LayoutKind.Sequential, Pack = 8)]
+        struct VMStatistics64
+        {
+            public uint FreeCount;
+            public uint ActiveCount;
+            public uint InactiveCount;
+            public uint WireCount;
+            public ulong ZeroFillCount;
+            public ulong Reactivations;
+            public ulong Pageins;
+            public ulong Pageouts;
+            public ulong Faults;
+            public ulong CowFaults;
+            public ulong Lookups;
+            public ulong Hits;
+            public ulong Purges;
+            public uint PurgeableCount;
+            public uint SpeculativeCount;
+            public ulong Decompressions;
+            public ulong Compressions;
+            public ulong Swapins;
+            public ulong Swapouts;
+            public uint CompressorPageCount;
+            public uint ThrottledCount;
+            public uint ExternalPageCount;
+            public uint InternalPageCount;
+            public ulong TotalUncompressedPagesInCompressor;
+        }
+
+        [LibraryImport(SystemLibraryName, SetLastError = true)]
+        private static partial int host_statistics64(uint hostPriv, int hostFlavor, ref VMStatistics64 hostInfo64Out, ref uint hostInfo64OutCnt);
+    }
+}
diff --git a/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs
new file mode 100644
index 00000000..38728b9c
--- /dev/null
+++ b/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs
@@ -0,0 +1,79 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.UI.Common.Helper;
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
+
+namespace Ryujinx.UI.Common.SystemInfo
+{
+    public class SystemInfo
+    {
+        public string OsDescription { get; protected set; }
+        public string CpuName { get; protected set; }
+        public ulong RamTotal { get; protected set; }
+        public ulong RamAvailable { get; protected set; }
+        protected static int LogicalCoreCount => Environment.ProcessorCount;
+
+        protected SystemInfo()
+        {
+            OsDescription = $"{RuntimeInformation.OSDescription} ({RuntimeInformation.OSArchitecture})";
+            CpuName = "Unknown";
+        }
+
+        private static string ToGBString(ulong bytesValue) => (bytesValue == 0) ? "Unknown" : ValueFormatUtils.FormatFileSize((long)bytesValue, ValueFormatUtils.FileSizeUnits.Gibibytes);
+
+        public void Print()
+        {
+            Logger.Notice.Print(LogClass.Application, $"Operating System: {OsDescription}");
+            Logger.Notice.Print(LogClass.Application, $"CPU: {CpuName}");
+            Logger.Notice.Print(LogClass.Application, $"RAM: Total {ToGBString(RamTotal)} ; Available {ToGBString(RamAvailable)}");
+        }
+
+        public static SystemInfo Gather()
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                return new WindowsSystemInfo();
+            }
+            else if (OperatingSystem.IsLinux())
+            {
+                return new LinuxSystemInfo();
+            }
+            else if (OperatingSystem.IsMacOS())
+            {
+                return new MacOSSystemInfo();
+            }
+
+            Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform");
+
+            return new SystemInfo();
+        }
+
+        // x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004.
+        internal static string GetCpuidCpuName()
+        {
+            if (!X86Base.IsSupported)
+            {
+                return null;
+            }
+
+            // Check if CPU supports the query
+            if ((uint)X86Base.CpuId(unchecked((int)0x80000000), 0).Eax < 0x80000004)
+            {
+                return null;
+            }
+
+            int[] regs = new int[12];
+
+            for (uint i = 0; i < 3; ++i)
+            {
+                (regs[4 * i], regs[4 * i + 1], regs[4 * i + 2], regs[4 * i + 3]) = X86Base.CpuId((int)(0x80000002 + i), 0);
+            }
+
+            string name = Encoding.ASCII.GetString(MemoryMarshal.Cast<int, byte>(regs)).Replace('\0', ' ').Trim();
+
+            return string.IsNullOrEmpty(name) ? null : name;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs
new file mode 100644
index 00000000..bf49c2a6
--- /dev/null
+++ b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs
@@ -0,0 +1,87 @@
+using Ryujinx.Common.Logging;
+using System;
+using System.Management;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.SystemInfo
+{
+    [SupportedOSPlatform("windows")]
+    partial class WindowsSystemInfo : SystemInfo
+    {
+        internal WindowsSystemInfo()
+        {
+            CpuName = $"{GetCpuidCpuName() ?? GetCpuNameWMI()} ; {LogicalCoreCount} logical"; // WMI is very slow
+            (RamTotal, RamAvailable) = GetMemoryStats();
+        }
+
+        private static (ulong Total, ulong Available) GetMemoryStats()
+        {
+            MemoryStatusEx memStatus = new();
+            if (GlobalMemoryStatusEx(ref memStatus))
+            {
+                return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
+            }
+
+            Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
+
+            return (0, 0);
+        }
+
+        private static string GetCpuNameWMI()
+        {
+            ManagementObjectCollection cpuObjs = GetWMIObjects("root\\CIMV2", "SELECT * FROM Win32_Processor");
+
+            if (cpuObjs != null)
+            {
+                foreach (var cpuObj in cpuObjs)
+                {
+                    return cpuObj["Name"].ToString().Trim();
+                }
+            }
+
+            return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim();
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct MemoryStatusEx
+        {
+            public uint Length;
+            public uint MemoryLoad;
+            public ulong TotalPhys;
+            public ulong AvailPhys;
+            public ulong TotalPageFile;
+            public ulong AvailPageFile;
+            public ulong TotalVirtual;
+            public ulong AvailVirtual;
+            public ulong AvailExtendedVirtual;
+
+            public MemoryStatusEx()
+            {
+                Length = (uint)Marshal.SizeOf<MemoryStatusEx>();
+            }
+        }
+
+        [LibraryImport("kernel32.dll", SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static partial bool GlobalMemoryStatusEx(ref MemoryStatusEx lpBuffer);
+
+        private static ManagementObjectCollection GetWMIObjects(string scope, string query)
+        {
+            try
+            {
+                return new ManagementObjectSearcher(scope, query).Get();
+            }
+            catch (PlatformNotSupportedException ex)
+            {
+                Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
+            }
+            catch (COMException ex)
+            {
+                Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
+            }
+
+            return null;
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.Common/UserError.cs b/src/Ryujinx.UI.Common/UserError.cs
new file mode 100644
index 00000000..706971ef
--- /dev/null
+++ b/src/Ryujinx.UI.Common/UserError.cs
@@ -0,0 +1,39 @@
+namespace Ryujinx.UI.Common
+{
+    /// <summary>
+    /// Represent a common error that could be reported to the user by the emulator.
+    /// </summary>
+    public enum UserError
+    {
+        /// <summary>
+        /// No error to report.
+        /// </summary>
+        Success = 0x0,
+
+        /// <summary>
+        /// No keys are present.
+        /// </summary>
+        NoKeys = 0x1,
+
+        /// <summary>
+        /// No firmware is installed.
+        /// </summary>
+        NoFirmware = 0x2,
+
+        /// <summary>
+        /// Firmware parsing failed.
+        /// </summary>
+        /// <remarks>Most likely related to keys.</remarks>
+        FirmwareParsingFailed = 0x3,
+
+        /// <summary>
+        /// No application was found at the given path.
+        /// </summary>
+        ApplicationNotFound = 0x4,
+
+        /// <summary>
+        /// An unknown error.
+        /// </summary>
+        Unknown = 0xDEAD,
+    }
+}
diff --git a/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs
new file mode 100644
index 00000000..bb4918d5
--- /dev/null
+++ b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs
@@ -0,0 +1,33 @@
+using Microsoft.CodeAnalysis;
+using System.Linq;
+using System.Text;
+
+namespace Ryujinx.UI.LocaleGenerator
+{
+    [Generator]
+    public class LocaleGenerator : IIncrementalGenerator
+    {
+        public void Initialize(IncrementalGeneratorInitializationContext context)
+        {
+            var englishLocaleFile = context.AdditionalTextsProvider.Where(static x => x.Path.EndsWith("en_US.json"));
+
+            IncrementalValuesProvider<string> contents = englishLocaleFile.Select((text, cancellationToken) => text.GetText(cancellationToken)!.ToString());
+
+            context.RegisterSourceOutput(contents, (spc, content) =>
+            {
+                var lines = content.Split('\n').Where(x => x.Trim().StartsWith("\"")).Select(x => x.Split(':')[0].Trim().Replace("\"", ""));
+                StringBuilder enumSourceBuilder = new();
+                enumSourceBuilder.AppendLine("namespace Ryujinx.Ava.Common.Locale;");
+                enumSourceBuilder.AppendLine("internal enum LocaleKeys");
+                enumSourceBuilder.AppendLine("{");
+                foreach (var line in lines)
+                {
+                    enumSourceBuilder.AppendLine($"    {line},");
+                }
+                enumSourceBuilder.AppendLine("}");
+
+                spc.AddSource("LocaleKeys", enumSourceBuilder.ToString());
+            });
+        }
+    }
+}
diff --git a/src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj b/src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj
new file mode 100644
index 00000000..05cbc764
--- /dev/null
+++ b/src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <LangVersion>latest</LangVersion>
+    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationAddedEventArgs.cs b/src/Ryujinx.Ui.Common/App/ApplicationAddedEventArgs.cs
deleted file mode 100644
index 01e20276..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationAddedEventArgs.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Ryujinx.Ui.App.Common
-{
-    public class ApplicationAddedEventArgs : EventArgs
-    {
-        public ApplicationData AppData { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationCountUpdatedEventArgs.cs b/src/Ryujinx.Ui.Common/App/ApplicationCountUpdatedEventArgs.cs
deleted file mode 100644
index ca54ddf7..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationCountUpdatedEventArgs.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace Ryujinx.Ui.App.Common
-{
-    public class ApplicationCountUpdatedEventArgs : EventArgs
-    {
-        public int NumAppsFound { get; set; }
-        public int NumAppsLoaded { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationData.cs b/src/Ryujinx.Ui.Common/App/ApplicationData.cs
deleted file mode 100644
index bd844805..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationData.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Loader;
-using LibHac.Ns;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common.Logging;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.Common.Helper;
-using System;
-using System.IO;
-
-namespace Ryujinx.Ui.App.Common
-{
-    public class ApplicationData
-    {
-        public bool Favorite { get; set; }
-        public byte[] Icon { get; set; }
-        public string TitleName { get; set; }
-        public string TitleId { get; set; }
-        public string Developer { get; set; }
-        public string Version { get; set; }
-        public TimeSpan TimePlayed { get; set; }
-        public DateTime? LastPlayed { get; set; }
-        public string FileExtension { get; set; }
-        public long FileSize { get; set; }
-        public string Path { get; set; }
-        public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
-
-        public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
-
-        public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed);
-
-        public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
-
-        public static string GetApplicationBuildId(VirtualFileSystem virtualFileSystem, string titleFilePath)
-        {
-            using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
-
-            Nca mainNca = null;
-            Nca patchNca = null;
-
-            if (!System.IO.Path.Exists(titleFilePath))
-            {
-                Logger.Error?.Print(LogClass.Application, $"File does not exists. {titleFilePath}");
-                return string.Empty;
-            }
-
-            string extension = System.IO.Path.GetExtension(titleFilePath).ToLower();
-
-            if (extension is ".nsp" or ".xci")
-            {
-                IFileSystem pfs;
-
-                if (extension == ".xci")
-                {
-                    Xci xci = new(virtualFileSystem.KeySet, file.AsStorage());
-
-                    pfs = xci.OpenPartition(XciPartitionType.Secure);
-                }
-                else
-                {
-                    var pfsTemp = new PartitionFileSystem();
-                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
-                    pfs = pfsTemp;
-                }
-
-                foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
-                {
-                    using var ncaFile = new UniqueRef<IFile>();
-
-                    pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                    Nca nca = new(virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
-
-                    if (nca.Header.ContentType != NcaContentType.Program)
-                    {
-                        continue;
-                    }
-
-                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
-
-                    if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
-                    {
-                        patchNca = nca;
-                    }
-                    else
-                    {
-                        mainNca = nca;
-                    }
-                }
-            }
-            else if (extension == ".nca")
-            {
-                mainNca = new Nca(virtualFileSystem.KeySet, file.AsStorage());
-            }
-
-            if (mainNca == null)
-            {
-                Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file");
-
-                return string.Empty;
-            }
-
-            (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _);
-
-            if (updatePatchNca != null)
-            {
-                patchNca = updatePatchNca;
-            }
-
-            IFileSystem codeFs = null;
-
-            if (patchNca == null)
-            {
-                if (mainNca.CanOpenSection(NcaSectionType.Code))
-                {
-                    codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
-                }
-            }
-            else
-            {
-                if (patchNca.CanOpenSection(NcaSectionType.Code))
-                {
-                    codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
-                }
-            }
-
-            if (codeFs == null)
-            {
-                Logger.Error?.Print(LogClass.Loader, "No ExeFS found in NCA");
-
-                return string.Empty;
-            }
-
-            const string MainExeFs = "main";
-
-            if (!codeFs.FileExists($"/{MainExeFs}"))
-            {
-                Logger.Error?.Print(LogClass.Loader, "No main binary ExeFS found in ExeFS");
-
-                return string.Empty;
-            }
-
-            using var nsoFile = new UniqueRef<IFile>();
-
-            codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-            NsoReader reader = new();
-            reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
-
-            return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationJsonSerializerContext.cs b/src/Ryujinx.Ui.Common/App/ApplicationJsonSerializerContext.cs
deleted file mode 100644
index 9a7b3edd..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationJsonSerializerContext.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.App.Common
-{
-    [JsonSourceGenerationOptions(WriteIndented = true)]
-    [JsonSerializable(typeof(ApplicationMetadata))]
-    internal partial class ApplicationJsonSerializerContext : JsonSerializerContext
-    {
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs b/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
deleted file mode 100644
index 3b35ff27..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
+++ /dev/null
@@ -1,930 +0,0 @@
-using LibHac;
-using LibHac.Common;
-using LibHac.Common.Keys;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Ns;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS.SystemState;
-using Ryujinx.HLE.Loaders.Npdm;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration.System;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Text.Json;
-using System.Threading;
-using Path = System.IO.Path;
-using TimeSpan = System.TimeSpan;
-
-namespace Ryujinx.Ui.App.Common
-{
-    public class ApplicationLibrary
-    {
-        public event EventHandler<ApplicationAddedEventArgs> ApplicationAdded;
-        public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
-
-        private readonly byte[] _nspIcon;
-        private readonly byte[] _xciIcon;
-        private readonly byte[] _ncaIcon;
-        private readonly byte[] _nroIcon;
-        private readonly byte[] _nsoIcon;
-
-        private readonly VirtualFileSystem _virtualFileSystem;
-        private Language _desiredTitleLanguage;
-        private CancellationTokenSource _cancellationToken;
-
-        private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-        private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-        public ApplicationLibrary(VirtualFileSystem virtualFileSystem)
-        {
-            _virtualFileSystem = virtualFileSystem;
-
-            _nspIcon = GetResourceBytes("Ryujinx.Ui.Common.Resources.Icon_NSP.png");
-            _xciIcon = GetResourceBytes("Ryujinx.Ui.Common.Resources.Icon_XCI.png");
-            _ncaIcon = GetResourceBytes("Ryujinx.Ui.Common.Resources.Icon_NCA.png");
-            _nroIcon = GetResourceBytes("Ryujinx.Ui.Common.Resources.Icon_NRO.png");
-            _nsoIcon = GetResourceBytes("Ryujinx.Ui.Common.Resources.Icon_NSO.png");
-        }
-
-        private static byte[] GetResourceBytes(string resourceName)
-        {
-            Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
-            byte[] resourceByteArray = new byte[resourceStream.Length];
-
-            resourceStream.Read(resourceByteArray);
-
-            return resourceByteArray;
-        }
-
-        public void CancelLoading()
-        {
-            _cancellationToken?.Cancel();
-        }
-
-        public static void ReadControlData(IFileSystem controlFs, Span<byte> outProperty)
-        {
-            using UniqueRef<IFile> controlFile = new();
-
-            controlFs.OpenFile(ref controlFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-            controlFile.Get.Read(out _, 0, outProperty, ReadOption.None).ThrowIfFailure();
-        }
-
-        public void LoadApplications(List<string> appDirs, Language desiredTitleLanguage)
-        {
-            int numApplicationsFound = 0;
-            int numApplicationsLoaded = 0;
-
-            _desiredTitleLanguage = desiredTitleLanguage;
-
-            _cancellationToken = new CancellationTokenSource();
-
-            // Builds the applications list with paths to found applications
-            List<string> applications = new();
-
-            try
-            {
-                foreach (string appDir in appDirs)
-                {
-                    if (_cancellationToken.Token.IsCancellationRequested)
-                    {
-                        return;
-                    }
-
-                    if (!Directory.Exists(appDir))
-                    {
-                        Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid directory: \"{appDir}\"");
-
-                        continue;
-                    }
-
-                    try
-                    {
-                        IEnumerable<string> files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file =>
-                        {
-                            return
-                            (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value) ||
-                            (Path.GetExtension(file).ToLower() is ".pfs0" && ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value) ||
-                            (Path.GetExtension(file).ToLower() is ".xci" && ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value) ||
-                            (Path.GetExtension(file).ToLower() is ".nca" && ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value) ||
-                            (Path.GetExtension(file).ToLower() is ".nro" && ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value) ||
-                            (Path.GetExtension(file).ToLower() is ".nso" && ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value);
-                        });
-
-                        foreach (string app in files)
-                        {
-                            if (_cancellationToken.Token.IsCancellationRequested)
-                            {
-                                return;
-                            }
-
-                            var fileInfo = new FileInfo(app);
-                            string extension = fileInfo.Extension.ToLower();
-
-                            if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden) && extension is ".nsp" or ".pfs0" or ".xci" or ".nca" or ".nro" or ".nso")
-                            {
-                                var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName;
-
-                                if (!File.Exists(fullPath))
-                                {
-                                    Logger.Warning?.Print(LogClass.Application, $"Skipping invalid symlink: {fileInfo.FullName}");
-                                    continue;
-                                }
-
-                                applications.Add(fullPath);
-                                numApplicationsFound++;
-                            }
-                        }
-                    }
-                    catch (UnauthorizedAccessException)
-                    {
-                        Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{appDir}\"");
-                    }
-                }
-
-                // Loops through applications list, creating a struct and then firing an event containing the struct for each application
-                foreach (string applicationPath in applications)
-                {
-                    if (_cancellationToken.Token.IsCancellationRequested)
-                    {
-                        return;
-                    }
-
-                    long fileSize = new FileInfo(applicationPath).Length;
-                    string titleName = "Unknown";
-                    string titleId = "0000000000000000";
-                    string developer = "Unknown";
-                    string version = "0";
-                    byte[] applicationIcon = null;
-
-                    BlitStruct<ApplicationControlProperty> controlHolder = new(1);
-
-                    try
-                    {
-                        string extension = Path.GetExtension(applicationPath).ToLower();
-
-                        using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read);
-
-                        if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
-                        {
-                            try
-                            {
-                                IFileSystem pfs;
-
-                                bool isExeFs = false;
-
-                                if (extension == ".xci")
-                                {
-                                    Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
-
-                                    pfs = xci.OpenPartition(XciPartitionType.Secure);
-                                }
-                                else
-                                {
-                                    var pfsTemp = new PartitionFileSystem();
-                                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
-                                    pfs = pfsTemp;
-
-                                    // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
-                                    bool hasMainNca = false;
-
-                                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
-                                    {
-                                        if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
-                                        {
-                                            using UniqueRef<IFile> ncaFile = new();
-
-                                            pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                                            Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
-                                            int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
-
-                                            // Some main NCAs don't have a data partition, so check if the partition exists before opening it
-                                            if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
-                                            {
-                                                hasMainNca = true;
-
-                                                break;
-                                            }
-                                        }
-                                        else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
-                                        {
-                                            isExeFs = true;
-                                        }
-                                    }
-
-                                    if (!hasMainNca && !isExeFs)
-                                    {
-                                        numApplicationsFound--;
-
-                                        continue;
-                                    }
-                                }
-
-                                if (isExeFs)
-                                {
-                                    applicationIcon = _nspIcon;
-
-                                    using UniqueRef<IFile> npdmFile = new();
-
-                                    Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read);
-
-                                    if (ResultFs.PathNotFound.Includes(result))
-                                    {
-                                        Npdm npdm = new(npdmFile.Get.AsStream());
-
-                                        titleName = npdm.TitleName;
-                                        titleId = npdm.Aci0.TitleId.ToString("x16");
-                                    }
-                                }
-                                else
-                                {
-                                    GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);
-
-                                    // Check if there is an update available.
-                                    if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs))
-                                    {
-                                        // Replace the original ControlFs by the updated one.
-                                        controlFs = updatedControlFs;
-                                    }
-
-                                    ReadControlData(controlFs, controlHolder.ByteSpan);
-
-                                    GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version);
-
-                                    // Read the icon from the ControlFS and store it as a byte array
-                                    try
-                                    {
-                                        using UniqueRef<IFile> icon = new();
-
-                                        controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                                        using MemoryStream stream = new();
-
-                                        icon.Get.AsStream().CopyTo(stream);
-                                        applicationIcon = stream.ToArray();
-                                    }
-                                    catch (HorizonResultException)
-                                    {
-                                        foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
-                                        {
-                                            if (entry.Name == "control.nacp")
-                                            {
-                                                continue;
-                                            }
-
-                                            using var icon = new UniqueRef<IFile>();
-
-                                            controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                                            using MemoryStream stream = new();
-
-                                            icon.Get.AsStream().CopyTo(stream);
-                                            applicationIcon = stream.ToArray();
-
-                                            if (applicationIcon != null)
-                                            {
-                                                break;
-                                            }
-                                        }
-
-                                        applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon;
-                                    }
-                                }
-                            }
-                            catch (MissingKeyException exception)
-                            {
-                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
-
-                                Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
-                            }
-                            catch (InvalidDataException)
-                            {
-                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
-
-                                Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
-                            }
-                            catch (Exception exception)
-                            {
-                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
-
-                                numApplicationsFound--;
-
-                                continue;
-                            }
-                        }
-                        else if (extension == ".nro")
-                        {
-                            BinaryReader reader = new(file);
-
-                            byte[] Read(long position, int size)
-                            {
-                                file.Seek(position, SeekOrigin.Begin);
-
-                                return reader.ReadBytes(size);
-                            }
-
-                            try
-                            {
-                                file.Seek(24, SeekOrigin.Begin);
-
-                                int assetOffset = reader.ReadInt32();
-
-                                if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
-                                {
-                                    byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
-
-                                    long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
-                                    long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
-
-                                    ulong nacpOffset = reader.ReadUInt64();
-                                    ulong nacpSize = reader.ReadUInt64();
-
-                                    // Reads and stores game icon as byte array
-                                    if (iconSize > 0)
-                                    {
-                                        applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);
-                                    }
-                                    else
-                                    {
-                                        applicationIcon = _nroIcon;
-                                    }
-
-                                    // Read the NACP data
-                                    Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);
-
-                                    GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version);
-                                }
-                                else
-                                {
-                                    applicationIcon = _nroIcon;
-                                    titleName = Path.GetFileNameWithoutExtension(applicationPath);
-                                }
-                            }
-                            catch
-                            {
-                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
-
-                                numApplicationsFound--;
-
-                                continue;
-                            }
-                        }
-                        else if (extension == ".nca")
-                        {
-                            try
-                            {
-                                Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
-                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
-
-                                if (nca.Header.ContentType != NcaContentType.Program || (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
-                                {
-                                    numApplicationsFound--;
-
-                                    continue;
-                                }
-                            }
-                            catch (InvalidDataException)
-                            {
-                                Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}");
-                            }
-                            catch
-                            {
-                                Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
-
-                                numApplicationsFound--;
-
-                                continue;
-                            }
-
-                            applicationIcon = _ncaIcon;
-                            titleName = Path.GetFileNameWithoutExtension(applicationPath);
-                        }
-                        // If its an NSO we just set defaults
-                        else if (extension == ".nso")
-                        {
-                            applicationIcon = _nsoIcon;
-                            titleName = Path.GetFileNameWithoutExtension(applicationPath);
-                        }
-                    }
-                    catch (IOException exception)
-                    {
-                        Logger.Warning?.Print(LogClass.Application, exception.Message);
-
-                        numApplicationsFound--;
-
-                        continue;
-                    }
-
-                    ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId, appMetadata =>
-                    {
-                        appMetadata.Title = titleName;
-
-                        // Only do the migration if time_played has a value and timespan_played hasn't been updated yet.
-                        if (appMetadata.TimePlayedOld != default && appMetadata.TimePlayed == TimeSpan.Zero)
-                        {
-                            appMetadata.TimePlayed = TimeSpan.FromSeconds(appMetadata.TimePlayedOld);
-                            appMetadata.TimePlayedOld = default;
-                        }
-
-                        // Only do the migration if last_played has a value and last_played_utc doesn't exist yet.
-                        if (appMetadata.LastPlayedOld != default && !appMetadata.LastPlayed.HasValue)
-                        {
-                            // Migrate from string-based last_played to DateTime-based last_played_utc.
-                            if (DateTime.TryParse(appMetadata.LastPlayedOld, out DateTime lastPlayedOldParsed))
-                            {
-                                appMetadata.LastPlayed = lastPlayedOldParsed;
-
-                                // Migration successful: deleting last_played from the metadata file.
-                                appMetadata.LastPlayedOld = default;
-                            }
-
-                        }
-                    });
-
-                    ApplicationData data = new()
-                    {
-                        Favorite = appMetadata.Favorite,
-                        Icon = applicationIcon,
-                        TitleName = titleName,
-                        TitleId = titleId,
-                        Developer = developer,
-                        Version = version,
-                        TimePlayed = appMetadata.TimePlayed,
-                        LastPlayed = appMetadata.LastPlayed,
-                        FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper(),
-                        FileSize = fileSize,
-                        Path = applicationPath,
-                        ControlHolder = controlHolder,
-                    };
-
-                    numApplicationsLoaded++;
-
-                    OnApplicationAdded(new ApplicationAddedEventArgs
-                    {
-                        AppData = data,
-                    });
-
-                    OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
-                    {
-                        NumAppsFound = numApplicationsFound,
-                        NumAppsLoaded = numApplicationsLoaded,
-                    });
-                }
-
-                OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs
-                {
-                    NumAppsFound = numApplicationsFound,
-                    NumAppsLoaded = numApplicationsLoaded,
-                });
-            }
-            finally
-            {
-                _cancellationToken.Dispose();
-                _cancellationToken = null;
-            }
-        }
-
-        protected void OnApplicationAdded(ApplicationAddedEventArgs e)
-        {
-            ApplicationAdded?.Invoke(null, e);
-        }
-
-        protected void OnApplicationCountUpdated(ApplicationCountUpdatedEventArgs e)
-        {
-            ApplicationCountUpdated?.Invoke(null, e);
-        }
-
-        private void GetControlFsAndTitleId(IFileSystem pfs, out IFileSystem controlFs, out string titleId)
-        {
-            (_, _, Nca controlNca) = GetGameData(_virtualFileSystem, pfs, 0);
-
-            // Return the ControlFS
-            controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
-            titleId = controlNca?.Header.TitleId.ToString("x16");
-        }
-
-        public static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
-        {
-            string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui");
-            string metadataFile = Path.Combine(metadataFolder, "metadata.json");
-
-            ApplicationMetadata appMetadata;
-
-            if (!File.Exists(metadataFile))
-            {
-                Directory.CreateDirectory(metadataFolder);
-
-                appMetadata = new ApplicationMetadata();
-
-                JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
-            }
-
-            try
-            {
-                appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata);
-            }
-            catch (JsonException)
-            {
-                Logger.Warning?.Print(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults.");
-
-                appMetadata = new ApplicationMetadata();
-            }
-
-            if (modifyFunction != null)
-            {
-                modifyFunction(appMetadata);
-
-                JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata);
-            }
-
-            return appMetadata;
-        }
-
-        public byte[] GetApplicationIcon(string applicationPath, Language desiredTitleLanguage)
-        {
-            byte[] applicationIcon = null;
-
-            try
-            {
-                // Look for icon only if applicationPath is not a directory
-                if (!Directory.Exists(applicationPath))
-                {
-                    string extension = Path.GetExtension(applicationPath).ToLower();
-
-                    using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read);
-
-                    if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
-                    {
-                        try
-                        {
-                            IFileSystem pfs;
-
-                            bool isExeFs = false;
-
-                            if (extension == ".xci")
-                            {
-                                Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
-
-                                pfs = xci.OpenPartition(XciPartitionType.Secure);
-                            }
-                            else
-                            {
-                                var pfsTemp = new PartitionFileSystem();
-                                pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
-                                pfs = pfsTemp;
-
-                                foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
-                                {
-                                    if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
-                                    {
-                                        isExeFs = true;
-                                    }
-                                }
-                            }
-
-                            if (isExeFs)
-                            {
-                                applicationIcon = _nspIcon;
-                            }
-                            else
-                            {
-                                // Store the ControlFS in variable called controlFs
-                                GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out _);
-
-                                // Read the icon from the ControlFS and store it as a byte array
-                                try
-                                {
-                                    using var icon = new UniqueRef<IFile>();
-
-                                    controlFs.OpenFile(ref icon.Ref, $"/icon_{desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                                    using MemoryStream stream = new();
-
-                                    icon.Get.AsStream().CopyTo(stream);
-                                    applicationIcon = stream.ToArray();
-                                }
-                                catch (HorizonResultException)
-                                {
-                                    foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
-                                    {
-                                        if (entry.Name == "control.nacp")
-                                        {
-                                            continue;
-                                        }
-
-                                        using var icon = new UniqueRef<IFile>();
-
-                                        controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                                        using (MemoryStream stream = new())
-                                        {
-                                            icon.Get.AsStream().CopyTo(stream);
-                                            applicationIcon = stream.ToArray();
-                                        }
-
-                                        if (applicationIcon != null)
-                                        {
-                                            break;
-                                        }
-                                    }
-
-                                    applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon;
-                                }
-                            }
-                        }
-                        catch (MissingKeyException)
-                        {
-                            applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
-                        }
-                        catch (InvalidDataException)
-                        {
-                            applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
-                        }
-                        catch (Exception exception)
-                        {
-                            Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
-                        }
-                    }
-                    else if (extension == ".nro")
-                    {
-                        BinaryReader reader = new(file);
-
-                        byte[] Read(long position, int size)
-                        {
-                            file.Seek(position, SeekOrigin.Begin);
-
-                            return reader.ReadBytes(size);
-                        }
-
-                        try
-                        {
-                            file.Seek(24, SeekOrigin.Begin);
-
-                            int assetOffset = reader.ReadInt32();
-
-                            if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
-                            {
-                                byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
-
-                                long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
-                                long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
-
-                                // Reads and stores game icon as byte array
-                                if (iconSize > 0)
-                                {
-                                    applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);
-                                }
-                                else
-                                {
-                                    applicationIcon = _nroIcon;
-                                }
-                            }
-                            else
-                            {
-                                applicationIcon = _nroIcon;
-                            }
-                        }
-                        catch
-                        {
-                            Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
-                        }
-                    }
-                    else if (extension == ".nca")
-                    {
-                        applicationIcon = _ncaIcon;
-                    }
-                    // If its an NSO we just set defaults
-                    else if (extension == ".nso")
-                    {
-                        applicationIcon = _nsoIcon;
-                    }
-                }
-            }
-            catch (Exception)
-            {
-                Logger.Warning?.Print(LogClass.Application, $"Could not retrieve a valid icon for the app. Default icon will be used. Errored File: {applicationPath}");
-            }
-
-            return applicationIcon ?? _ncaIcon;
-        }
-
-        private void GetGameInformation(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher, out string version)
-        {
-            _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
-
-            if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
-            {
-                titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
-                publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
-            }
-            else
-            {
-                titleName = null;
-                publisher = null;
-            }
-
-            if (string.IsNullOrWhiteSpace(titleName))
-            {
-                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
-                {
-                    if (!controlTitle.NameString.IsEmpty())
-                    {
-                        titleName = controlTitle.NameString.ToString();
-
-                        break;
-                    }
-                }
-            }
-
-            if (string.IsNullOrWhiteSpace(publisher))
-            {
-                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
-                {
-                    if (!controlTitle.PublisherString.IsEmpty())
-                    {
-                        publisher = controlTitle.PublisherString.ToString();
-
-                        break;
-                    }
-                }
-            }
-
-            if (controlData.PresenceGroupId != 0)
-            {
-                titleId = controlData.PresenceGroupId.ToString("x16");
-            }
-            else if (controlData.SaveDataOwnerId != 0)
-            {
-                titleId = controlData.SaveDataOwnerId.ToString();
-            }
-            else if (controlData.AddOnContentBaseId != 0)
-            {
-                titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
-            }
-            else
-            {
-                titleId = "0000000000000000";
-            }
-
-            version = controlData.DisplayVersionString.ToString();
-        }
-
-        private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs)
-        {
-            updatedControlFs = null;
-
-            string updatePath = "(unknown)";
-
-            try
-            {
-                (Nca patchNca, Nca controlNca) = GetGameUpdateData(_virtualFileSystem, titleId, 0, out updatePath);
-
-                if (patchNca != null && controlNca != null)
-                {
-                    updatedControlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
-
-                    return true;
-                }
-            }
-            catch (InvalidDataException)
-            {
-                Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {updatePath}");
-            }
-            catch (MissingKeyException exception)
-            {
-                Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}");
-            }
-
-            return false;
-        }
-
-        public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, IFileSystem pfs, int programIndex)
-        {
-            Nca mainNca = null;
-            Nca patchNca = null;
-            Nca controlNca = null;
-
-            fileSystem.ImportTickets(pfs);
-
-            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
-            {
-                using var ncaFile = new UniqueRef<IFile>();
-
-                pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
-
-                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
-
-                if (ncaProgramIndex != programIndex)
-                {
-                    continue;
-                }
-
-                if (nca.Header.ContentType == NcaContentType.Program)
-                {
-                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
-
-                    if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
-                    {
-                        patchNca = nca;
-                    }
-                    else
-                    {
-                        mainNca = nca;
-                    }
-                }
-                else if (nca.Header.ContentType == NcaContentType.Control)
-                {
-                    controlNca = nca;
-                }
-            }
-
-            return (mainNca, patchNca, controlNca);
-        }
-
-        public static (Nca patch, Nca control) GetGameUpdateDataFromPartition(VirtualFileSystem fileSystem, PartitionFileSystem pfs, string titleId, int programIndex)
-        {
-            Nca patchNca = null;
-            Nca controlNca = null;
-
-            fileSystem.ImportTickets(pfs);
-
-            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
-            {
-                using var ncaFile = new UniqueRef<IFile>();
-
-                pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
-
-                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
-
-                if (ncaProgramIndex != programIndex)
-                {
-                    continue;
-                }
-
-                if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
-                {
-                    break;
-                }
-
-                if (nca.Header.ContentType == NcaContentType.Program)
-                {
-                    patchNca = nca;
-                }
-                else if (nca.Header.ContentType == NcaContentType.Control)
-                {
-                    controlNca = nca;
-                }
-            }
-
-            return (patchNca, controlNca);
-        }
-
-        public static (Nca patch, Nca control) GetGameUpdateData(VirtualFileSystem fileSystem, string titleId, int programIndex, out string updatePath)
-        {
-            updatePath = null;
-
-            if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdBase))
-            {
-                // Clear the program index part.
-                titleIdBase &= ~0xFUL;
-
-                // Load update information if exists.
-                string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json");
-
-                if (File.Exists(titleUpdateMetadataPath))
-                {
-                    updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
-
-                    if (File.Exists(updatePath))
-                    {
-                        FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
-                        PartitionFileSystem nsp = new();
-                        nsp.Initialize(file.AsStorage()).ThrowIfFailure();
-
-                        return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
-                    }
-                }
-            }
-
-            return (null, null);
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationMetadata.cs b/src/Ryujinx.Ui.Common/App/ApplicationMetadata.cs
deleted file mode 100644
index 43647fee..00000000
--- a/src/Ryujinx.Ui.Common/App/ApplicationMetadata.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.App.Common
-{
-    public class ApplicationMetadata
-    {
-        public string Title { get; set; }
-        public bool Favorite { get; set; }
-
-        [JsonPropertyName("timespan_played")]
-        public TimeSpan TimePlayed { get; set; } = TimeSpan.Zero;
-
-        [JsonPropertyName("last_played_utc")]
-        public DateTime? LastPlayed { get; set; } = null;
-
-        [JsonPropertyName("time_played")]
-        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
-        public double TimePlayedOld { get; set; }
-
-        [JsonPropertyName("last_played")]
-        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
-        public string LastPlayedOld { get; set; }
-
-        /// <summary>
-        /// Updates <see cref="LastPlayed"/>. Call this before launching a game.
-        /// </summary>
-        public void UpdatePreGame()
-        {
-            LastPlayed = DateTime.UtcNow;
-        }
-
-        /// <summary>
-        /// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends.
-        /// </summary>
-        public void UpdatePostGame()
-        {
-            DateTime? prevLastPlayed = LastPlayed;
-            UpdatePreGame();
-
-            if (!prevLastPlayed.HasValue)
-            {
-                return;
-            }
-
-            TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value;
-            double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds;
-            TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero));
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/AudioBackend.cs b/src/Ryujinx.Ui.Common/Configuration/AudioBackend.cs
deleted file mode 100644
index dc0a5ac6..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/AudioBackend.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Ryujinx.Common.Utilities;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    [JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))]
-    public enum AudioBackend
-    {
-        Dummy,
-        OpenAl,
-        SoundIo,
-        SDL2,
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs
deleted file mode 100644
index 8a4db1fe..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Multiplayer;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Configuration.System;
-using Ryujinx.Ui.Common.Configuration.Ui;
-using System.Collections.Generic;
-using System.Text.Json.Nodes;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    public class ConfigurationFileFormat
-    {
-        /// <summary>
-        /// The current version of the file format
-        /// </summary>
-        public const int CurrentVersion = 48;
-
-        /// <summary>
-        /// Version of the configuration file format
-        /// </summary>
-        public int Version { get; set; }
-
-        /// <summary>
-        /// Enables or disables logging to a file on disk
-        /// </summary>
-        public bool EnableFileLog { get; set; }
-
-        /// <summary>
-        /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime.
-        /// </summary>
-        public BackendThreading BackendThreading { get; set; }
-
-        /// <summary>
-        /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead.
-        /// </summary>
-        public int ResScale { get; set; }
-
-        /// <summary>
-        /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.
-        /// </summary>
-        public float ResScaleCustom { get; set; }
-
-        /// <summary>
-        /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide.
-        /// </summary>
-        public float MaxAnisotropy { get; set; }
-
-        /// <summary>
-        /// Aspect Ratio applied to the renderer window.
-        /// </summary>
-        public AspectRatio AspectRatio { get; set; }
-
-        /// <summary>
-        /// Applies anti-aliasing to the renderer.
-        /// </summary>
-        public AntiAliasing AntiAliasing { get; set; }
-
-        /// <summary>
-        /// Sets the framebuffer upscaling type.
-        /// </summary>
-        public ScalingFilter ScalingFilter { get; set; }
-
-        /// <summary>
-        /// Sets the framebuffer upscaling level.
-        /// </summary>
-        public int ScalingFilterLevel { get; set; }
-
-        /// <summary>
-        /// Dumps shaders in this local directory
-        /// </summary>
-        public string GraphicsShadersDumpPath { get; set; }
-
-        /// <summary>
-        /// Enables printing debug log messages
-        /// </summary>
-        public bool LoggingEnableDebug { get; set; }
-
-        /// <summary>
-        /// Enables printing stub log messages
-        /// </summary>
-        public bool LoggingEnableStub { get; set; }
-
-        /// <summary>
-        /// Enables printing info log messages
-        /// </summary>
-        public bool LoggingEnableInfo { get; set; }
-
-        /// <summary>
-        /// Enables printing warning log messages
-        /// </summary>
-        public bool LoggingEnableWarn { get; set; }
-
-        /// <summary>
-        /// Enables printing error log messages
-        /// </summary>
-        public bool LoggingEnableError { get; set; }
-
-        /// <summary>
-        /// Enables printing trace log messages
-        /// </summary>
-        public bool LoggingEnableTrace { get; set; }
-
-        /// <summary>
-        /// Enables printing guest log messages
-        /// </summary>
-        public bool LoggingEnableGuest { get; set; }
-
-        /// <summary>
-        /// Enables printing FS access log messages
-        /// </summary>
-        public bool LoggingEnableFsAccessLog { get; set; }
-
-        /// <summary>
-        /// Controls which log messages are written to the log targets
-        /// </summary>
-        public LogClass[] LoggingFilteredClasses { get; set; }
-
-        /// <summary>
-        /// Change Graphics API debug log level
-        /// </summary>
-        public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; }
-
-        /// <summary>
-        /// Change System Language
-        /// </summary>
-        public Language SystemLanguage { get; set; }
-
-        /// <summary>
-        /// Change System Region
-        /// </summary>
-        public Region SystemRegion { get; set; }
-
-        /// <summary>
-        /// Change System TimeZone
-        /// </summary>
-        public string SystemTimeZone { get; set; }
-
-        /// <summary>
-        /// Change System Time Offset in seconds
-        /// </summary>
-        public long SystemTimeOffset { get; set; }
-
-        /// <summary>
-        /// Enables or disables Docked Mode
-        /// </summary>
-        public bool DockedMode { get; set; }
-
-        /// <summary>
-        /// Enables or disables Discord Rich Presence
-        /// </summary>
-        public bool EnableDiscordIntegration { get; set; }
-
-        /// <summary>
-        /// Checks for updates when Ryujinx starts when enabled
-        /// </summary>
-        public bool CheckUpdatesOnStart { get; set; }
-
-        /// <summary>
-        /// Show "Confirm Exit" Dialog
-        /// </summary>
-        public bool ShowConfirmExit { get; set; }
-
-        /// <summary>
-        /// Whether to hide cursor on idle, always or never
-        /// </summary>
-        public HideCursorMode HideCursor { get; set; }
-
-        /// <summary>
-        /// Enables or disables Vertical Sync
-        /// </summary>
-        public bool EnableVsync { get; set; }
-
-        /// <summary>
-        /// Enables or disables Shader cache
-        /// </summary>
-        public bool EnableShaderCache { get; set; }
-
-        /// <summary>
-        /// Enables or disables texture recompression
-        /// </summary>
-        public bool EnableTextureRecompression { get; set; }
-
-        /// <summary>
-        /// Enables or disables Macro high-level emulation
-        /// </summary>
-        public bool EnableMacroHLE { get; set; }
-
-        /// <summary>
-        /// Enables or disables color space passthrough, if available.
-        /// </summary>
-        public bool EnableColorSpacePassthrough { get; set; }
-
-        /// <summary>
-        /// Enables or disables profiled translation cache persistency
-        /// </summary>
-        public bool EnablePtc { get; set; }
-
-        /// <summary>
-        /// Enables or disables guest Internet access
-        /// </summary>
-        public bool EnableInternetAccess { get; set; }
-
-        /// <summary>
-        /// Enables integrity checks on Game content files
-        /// </summary>
-        public bool EnableFsIntegrityChecks { get; set; }
-
-        /// <summary>
-        /// Enables FS access log output to the console. Possible modes are 0-3
-        /// </summary>
-        public int FsGlobalAccessLogMode { get; set; }
-
-        /// <summary>
-        /// The selected audio backend
-        /// </summary>
-        public AudioBackend AudioBackend { get; set; }
-
-        /// <summary>
-        /// The audio volume
-        /// </summary>
-        public float AudioVolume { get; set; }
-
-        /// <summary>
-        /// The selected memory manager mode
-        /// </summary>
-        public MemoryManagerMode MemoryManagerMode { get; set; }
-
-        /// <summary>
-        /// Expands the RAM amount on the emulated system from 4GiB to 6GiB
-        /// </summary>
-        public bool ExpandRam { get; set; }
-
-        /// <summary>
-        /// Enable or disable ignoring missing services
-        /// </summary>
-        public bool IgnoreMissingServices { get; set; }
-
-        /// <summary>
-        /// Used to toggle columns in the GUI
-        /// </summary>
-        public GuiColumns GuiColumns { get; set; }
-
-        /// <summary>
-        /// Used to configure column sort settings in the GUI
-        /// </summary>
-        public ColumnSort ColumnSort { get; set; }
-
-        /// <summary>
-        /// A list of directories containing games to be used to load games into the games list
-        /// </summary>
-        public List<string> GameDirs { get; set; }
-
-        /// <summary>
-        /// A list of file types to be hidden in the games List
-        /// </summary>
-        public ShownFileTypes ShownFileTypes { get; set; }
-
-        /// <summary>
-        /// Main window start-up position, size and state
-        /// </summary>
-        public WindowStartup WindowStartup { get; set; }
-
-        /// <summary>
-        /// Language Code for the UI
-        /// </summary>
-        public string LanguageCode { get; set; }
-
-        /// <summary>
-        /// Enable or disable custom themes in the GUI
-        /// </summary>
-        public bool EnableCustomTheme { get; set; }
-
-        /// <summary>
-        /// Path to custom GUI theme
-        /// </summary>
-        public string CustomThemePath { get; set; }
-
-        /// <summary>
-        /// Chooses the base style // Not Used
-        /// </summary>
-        public string BaseStyle { get; set; }
-
-        /// <summary>
-        /// Chooses the view mode of the game list // Not Used
-        /// </summary>
-        public int GameListViewMode { get; set; }
-
-        /// <summary>
-        /// Show application name in Grid Mode // Not Used
-        /// </summary>
-        public bool ShowNames { get; set; }
-
-        /// <summary>
-        /// Sets App Icon Size // Not Used
-        /// </summary>
-        public int GridSize { get; set; }
-
-        /// <summary>
-        /// Sorts Apps in the game list // Not Used
-        /// </summary>
-        public int ApplicationSort { get; set; }
-
-        /// <summary>
-        /// Sets if Grid is ordered in Ascending Order // Not Used
-        /// </summary>
-        public bool IsAscendingOrder { get; set; }
-
-        /// <summary>
-        /// Start games in fullscreen mode
-        /// </summary>
-        public bool StartFullscreen { get; set; }
-
-        /// <summary>
-        /// Show console window
-        /// </summary>
-        public bool ShowConsole { get; set; }
-
-        /// <summary>
-        /// Enable or disable keyboard support (Independent from controllers binding)
-        /// </summary>
-        public bool EnableKeyboard { get; set; }
-
-        /// <summary>
-        /// Enable or disable mouse support (Independent from controllers binding)
-        /// </summary>
-        public bool EnableMouse { get; set; }
-
-        /// <summary>
-        /// Hotkey Keyboard Bindings
-        /// </summary>
-        public KeyboardHotkeys Hotkeys { get; set; }
-
-        /// <summary>
-        /// Legacy keyboard control bindings
-        /// </summary>
-        /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
-        /// TODO: Remove this when those older versions aren't in use anymore.
-        public List<JsonObject> KeyboardConfig { get; set; }
-
-        /// <summary>
-        /// Legacy controller control bindings
-        /// </summary>
-        /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
-        /// TODO: Remove this when those older versions aren't in use anymore.
-        public List<JsonObject> ControllerConfig { get; set; }
-
-        /// <summary>
-        /// Input configurations
-        /// </summary>
-        public List<InputConfig> InputConfig { get; set; }
-
-        /// <summary>
-        /// Graphics backend
-        /// </summary>
-        public GraphicsBackend GraphicsBackend { get; set; }
-
-        /// <summary>
-        /// Preferred GPU
-        /// </summary>
-        public string PreferredGpu { get; set; }
-
-        /// <summary>
-        /// Multiplayer Mode
-        /// </summary>
-        public MultiplayerMode MultiplayerMode { get; set; }
-
-        /// <summary>
-        /// GUID for the network interface used by LAN (or 0 for default)
-        /// </summary>
-        public string MultiplayerLanInterfaceId { get; set; }
-
-        /// <summary>
-        /// Uses Hypervisor over JIT if available
-        /// </summary>
-        public bool UseHypervisor { get; set; }
-
-        /// <summary>
-        /// Loads a configuration file from disk
-        /// </summary>
-        /// <param name="path">The path to the JSON configuration file</param>
-        /// <param name="configurationFileFormat">Parsed configuration file</param>
-        public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat)
-        {
-            try
-            {
-                configurationFileFormat = JsonHelper.DeserializeFromFile(path, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat);
-
-                return configurationFileFormat.Version != 0;
-            }
-            catch
-            {
-                configurationFileFormat = null;
-
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Save a configuration file to disk
-        /// </summary>
-        /// <param name="path">The path to the JSON configuration file</param>
-        public void SaveConfig(string path)
-        {
-            JsonHelper.SerializeToFile(path, this, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat);
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormatSettings.cs b/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormatSettings.cs
deleted file mode 100644
index 9a1841fc..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormatSettings.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Ryujinx.Common.Utilities;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    internal static class ConfigurationFileFormatSettings
-    {
-        public static readonly ConfigurationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/ConfigurationJsonSerializerContext.cs b/src/Ryujinx.Ui.Common/Configuration/ConfigurationJsonSerializerContext.cs
deleted file mode 100644
index 03989ede..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/ConfigurationJsonSerializerContext.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    [JsonSourceGenerationOptions(WriteIndented = true)]
-    [JsonSerializable(typeof(ConfigurationFileFormat))]
-    internal partial class ConfigurationJsonSerializerContext : JsonSerializerContext
-    {
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
deleted file mode 100644
index b017d384..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
+++ /dev/null
@@ -1,1562 +0,0 @@
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller;
-using Ryujinx.Common.Configuration.Hid.Keyboard;
-using Ryujinx.Common.Configuration.Multiplayer;
-using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.Vulkan;
-using Ryujinx.Ui.Common.Configuration.System;
-using Ryujinx.Ui.Common.Configuration.Ui;
-using Ryujinx.Ui.Common.Helper;
-using System;
-using System.Collections.Generic;
-using System.Text.Json.Nodes;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    public class ConfigurationState
-    {
-        /// <summary>
-        /// UI configuration section
-        /// </summary>
-        public class UiSection
-        {
-            public class Columns
-            {
-                public ReactiveObject<bool> FavColumn { get; private set; }
-                public ReactiveObject<bool> IconColumn { get; private set; }
-                public ReactiveObject<bool> AppColumn { get; private set; }
-                public ReactiveObject<bool> DevColumn { get; private set; }
-                public ReactiveObject<bool> VersionColumn { get; private set; }
-                public ReactiveObject<bool> TimePlayedColumn { get; private set; }
-                public ReactiveObject<bool> LastPlayedColumn { get; private set; }
-                public ReactiveObject<bool> FileExtColumn { get; private set; }
-                public ReactiveObject<bool> FileSizeColumn { get; private set; }
-                public ReactiveObject<bool> PathColumn { get; private set; }
-
-                public Columns()
-                {
-                    FavColumn = new ReactiveObject<bool>();
-                    IconColumn = new ReactiveObject<bool>();
-                    AppColumn = new ReactiveObject<bool>();
-                    DevColumn = new ReactiveObject<bool>();
-                    VersionColumn = new ReactiveObject<bool>();
-                    TimePlayedColumn = new ReactiveObject<bool>();
-                    LastPlayedColumn = new ReactiveObject<bool>();
-                    FileExtColumn = new ReactiveObject<bool>();
-                    FileSizeColumn = new ReactiveObject<bool>();
-                    PathColumn = new ReactiveObject<bool>();
-                }
-            }
-
-            public class ColumnSortSettings
-            {
-                public ReactiveObject<int> SortColumnId { get; private set; }
-                public ReactiveObject<bool> SortAscending { get; private set; }
-
-                public ColumnSortSettings()
-                {
-                    SortColumnId = new ReactiveObject<int>();
-                    SortAscending = new ReactiveObject<bool>();
-                }
-            }
-
-            /// <summary>
-            /// Used to toggle which file types are shown in the UI
-            /// </summary>
-            public class ShownFileTypeSettings
-            {
-                public ReactiveObject<bool> NSP { get; private set; }
-                public ReactiveObject<bool> PFS0 { get; private set; }
-                public ReactiveObject<bool> XCI { get; private set; }
-                public ReactiveObject<bool> NCA { get; private set; }
-                public ReactiveObject<bool> NRO { get; private set; }
-                public ReactiveObject<bool> NSO { get; private set; }
-
-                public ShownFileTypeSettings()
-                {
-                    NSP = new ReactiveObject<bool>();
-                    PFS0 = new ReactiveObject<bool>();
-                    XCI = new ReactiveObject<bool>();
-                    NCA = new ReactiveObject<bool>();
-                    NRO = new ReactiveObject<bool>();
-                    NSO = new ReactiveObject<bool>();
-                }
-            }
-
-            // <summary>
-            /// Determines main window start-up position, size and state
-            ///<summary>
-            public class WindowStartupSettings
-            {
-                public ReactiveObject<int> WindowSizeWidth { get; private set; }
-                public ReactiveObject<int> WindowSizeHeight { get; private set; }
-                public ReactiveObject<int> WindowPositionX { get; private set; }
-                public ReactiveObject<int> WindowPositionY { get; private set; }
-                public ReactiveObject<bool> WindowMaximized { get; private set; }
-
-                public WindowStartupSettings()
-                {
-                    WindowSizeWidth = new ReactiveObject<int>();
-                    WindowSizeHeight = new ReactiveObject<int>();
-                    WindowPositionX = new ReactiveObject<int>();
-                    WindowPositionY = new ReactiveObject<int>();
-                    WindowMaximized = new ReactiveObject<bool>();
-                }
-            }
-
-            /// <summary>
-            /// Used to toggle columns in the GUI
-            /// </summary>
-            public Columns GuiColumns { get; private set; }
-
-            /// <summary>
-            /// Used to configure column sort settings in the GUI
-            /// </summary>
-            public ColumnSortSettings ColumnSort { get; private set; }
-
-            /// <summary>
-            /// A list of directories containing games to be used to load games into the games list
-            /// </summary>
-            public ReactiveObject<List<string>> GameDirs { get; private set; }
-
-            /// <summary>
-            /// A list of file types to be hidden in the games List
-            /// </summary>
-            public ShownFileTypeSettings ShownFileTypes { get; private set; }
-
-            /// <summary>
-            /// Determines main window start-up position, size and state
-            /// </summary>
-            public WindowStartupSettings WindowStartup { get; private set; }
-
-            /// <summary>
-            /// Language Code for the UI
-            /// </summary>
-            public ReactiveObject<string> LanguageCode { get; private set; }
-
-            /// <summary>
-            /// Enable or disable custom themes in the GUI
-            /// </summary>
-            public ReactiveObject<bool> EnableCustomTheme { get; private set; }
-
-            /// <summary>
-            /// Path to custom GUI theme
-            /// </summary>
-            public ReactiveObject<string> CustomThemePath { get; private set; }
-
-            /// <summary>
-            /// Selects the base style
-            /// </summary>
-            public ReactiveObject<string> BaseStyle { get; private set; }
-
-            /// <summary>
-            /// Start games in fullscreen mode
-            /// </summary>
-            public ReactiveObject<bool> StartFullscreen { get; private set; }
-
-            /// <summary>
-            /// Hide / Show Console Window
-            /// </summary>
-            public ReactiveObject<bool> ShowConsole { get; private set; }
-
-            /// <summary>
-            /// View Mode of the Game list
-            /// </summary>
-            public ReactiveObject<int> GameListViewMode { get; private set; }
-
-            /// <summary>
-            /// Show application name in Grid Mode
-            /// </summary>
-            public ReactiveObject<bool> ShowNames { get; private set; }
-
-            /// <summary>
-            /// Sets App Icon Size in Grid Mode
-            /// </summary>
-            public ReactiveObject<int> GridSize { get; private set; }
-
-            /// <summary>
-            /// Sorts Apps in Grid Mode
-            /// </summary>
-            public ReactiveObject<int> ApplicationSort { get; private set; }
-
-            /// <summary>
-            /// Sets if Grid is ordered in Ascending Order
-            /// </summary>
-            public ReactiveObject<bool> IsAscendingOrder { get; private set; }
-
-            public UiSection()
-            {
-                GuiColumns = new Columns();
-                ColumnSort = new ColumnSortSettings();
-                GameDirs = new ReactiveObject<List<string>>();
-                ShownFileTypes = new ShownFileTypeSettings();
-                WindowStartup = new WindowStartupSettings();
-                EnableCustomTheme = new ReactiveObject<bool>();
-                CustomThemePath = new ReactiveObject<string>();
-                BaseStyle = new ReactiveObject<string>();
-                StartFullscreen = new ReactiveObject<bool>();
-                GameListViewMode = new ReactiveObject<int>();
-                ShowNames = new ReactiveObject<bool>();
-                GridSize = new ReactiveObject<int>();
-                ApplicationSort = new ReactiveObject<int>();
-                IsAscendingOrder = new ReactiveObject<bool>();
-                LanguageCode = new ReactiveObject<string>();
-                ShowConsole = new ReactiveObject<bool>();
-                ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
-            }
-        }
-
-        /// <summary>
-        /// Logger configuration section
-        /// </summary>
-        public class LoggerSection
-        {
-            /// <summary>
-            /// Enables printing debug log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableDebug { get; private set; }
-
-            /// <summary>
-            /// Enables printing stub log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableStub { get; private set; }
-
-            /// <summary>
-            /// Enables printing info log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableInfo { get; private set; }
-
-            /// <summary>
-            /// Enables printing warning log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableWarn { get; private set; }
-
-            /// <summary>
-            /// Enables printing error log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableError { get; private set; }
-
-            /// <summary>
-            /// Enables printing trace log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableTrace { get; private set; }
-
-            /// <summary>
-            /// Enables printing guest log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableGuest { get; private set; }
-
-            /// <summary>
-            /// Enables printing FS access log messages
-            /// </summary>
-            public ReactiveObject<bool> EnableFsAccessLog { get; private set; }
-
-            /// <summary>
-            /// Controls which log messages are written to the log targets
-            /// </summary>
-            public ReactiveObject<LogClass[]> FilteredClasses { get; private set; }
-
-            /// <summary>
-            /// Enables or disables logging to a file on disk
-            /// </summary>
-            public ReactiveObject<bool> EnableFileLog { get; private set; }
-
-            /// <summary>
-            /// Controls which OpenGL log messages are recorded in the log
-            /// </summary>
-            public ReactiveObject<GraphicsDebugLevel> GraphicsDebugLevel { get; private set; }
-
-            public LoggerSection()
-            {
-                EnableDebug = new ReactiveObject<bool>();
-                EnableStub = new ReactiveObject<bool>();
-                EnableInfo = new ReactiveObject<bool>();
-                EnableWarn = new ReactiveObject<bool>();
-                EnableError = new ReactiveObject<bool>();
-                EnableTrace = new ReactiveObject<bool>();
-                EnableGuest = new ReactiveObject<bool>();
-                EnableFsAccessLog = new ReactiveObject<bool>();
-                FilteredClasses = new ReactiveObject<LogClass[]>();
-                EnableFileLog = new ReactiveObject<bool>();
-                EnableFileLog.Event += static (sender, e) => LogValueChange(e, nameof(EnableFileLog));
-                GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
-            }
-        }
-
-        /// <summary>
-        /// System configuration section
-        /// </summary>
-        public class SystemSection
-        {
-            /// <summary>
-            /// Change System Language
-            /// </summary>
-            public ReactiveObject<Language> Language { get; private set; }
-
-            /// <summary>
-            /// Change System Region
-            /// </summary>
-            public ReactiveObject<Region> Region { get; private set; }
-
-            /// <summary>
-            /// Change System TimeZone
-            /// </summary>
-            public ReactiveObject<string> TimeZone { get; private set; }
-
-            /// <summary>
-            /// System Time Offset in Seconds
-            /// </summary>
-            public ReactiveObject<long> SystemTimeOffset { get; private set; }
-
-            /// <summary>
-            /// Enables or disables Docked Mode
-            /// </summary>
-            public ReactiveObject<bool> EnableDockedMode { get; private set; }
-
-            /// <summary>
-            /// Enables or disables profiled translation cache persistency
-            /// </summary>
-            public ReactiveObject<bool> EnablePtc { get; private set; }
-
-            /// <summary>
-            /// Enables or disables guest Internet access
-            /// </summary>
-            public ReactiveObject<bool> EnableInternetAccess { get; private set; }
-
-            /// <summary>
-            /// Enables integrity checks on Game content files
-            /// </summary>
-            public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
-
-            /// <summary>
-            /// Enables FS access log output to the console. Possible modes are 0-3
-            /// </summary>
-            public ReactiveObject<int> FsGlobalAccessLogMode { get; private set; }
-
-            /// <summary>
-            /// The selected audio backend
-            /// </summary>
-            public ReactiveObject<AudioBackend> AudioBackend { get; private set; }
-
-            /// <summary>
-            /// The audio backend volume
-            /// </summary>
-            public ReactiveObject<float> AudioVolume { get; private set; }
-
-            /// <summary>
-            /// The selected memory manager mode
-            /// </summary>
-            public ReactiveObject<MemoryManagerMode> MemoryManagerMode { get; private set; }
-
-            /// <summary>
-            /// Defines the amount of RAM available on the emulated system, and how it is distributed
-            /// </summary>
-            public ReactiveObject<bool> ExpandRam { get; private set; }
-
-            /// <summary>
-            /// Enable or disable ignoring missing services
-            /// </summary>
-            public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
-
-            /// <summary>
-            /// Uses Hypervisor over JIT if available
-            /// </summary>
-            public ReactiveObject<bool> UseHypervisor { get; private set; }
-
-            public SystemSection()
-            {
-                Language = new ReactiveObject<Language>();
-                Region = new ReactiveObject<Region>();
-                TimeZone = new ReactiveObject<string>();
-                SystemTimeOffset = new ReactiveObject<long>();
-                EnableDockedMode = new ReactiveObject<bool>();
-                EnableDockedMode.Event += static (sender, e) => LogValueChange(e, nameof(EnableDockedMode));
-                EnablePtc = new ReactiveObject<bool>();
-                EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
-                EnableInternetAccess = new ReactiveObject<bool>();
-                EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess));
-                EnableFsIntegrityChecks = new ReactiveObject<bool>();
-                EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks));
-                FsGlobalAccessLogMode = new ReactiveObject<int>();
-                FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(e, nameof(FsGlobalAccessLogMode));
-                AudioBackend = new ReactiveObject<AudioBackend>();
-                AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend));
-                MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
-                MemoryManagerMode.Event += static (sender, e) => LogValueChange(e, nameof(MemoryManagerMode));
-                ExpandRam = new ReactiveObject<bool>();
-                ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam));
-                IgnoreMissingServices = new ReactiveObject<bool>();
-                IgnoreMissingServices.Event += static (sender, e) => LogValueChange(e, nameof(IgnoreMissingServices));
-                AudioVolume = new ReactiveObject<float>();
-                AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume));
-                UseHypervisor = new ReactiveObject<bool>();
-                UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor));
-            }
-        }
-
-        /// <summary>
-        /// Hid configuration section
-        /// </summary>
-        public class HidSection
-        {
-            /// <summary>
-            /// Enable or disable keyboard support (Independent from controllers binding)
-            /// </summary>
-            public ReactiveObject<bool> EnableKeyboard { get; private set; }
-
-            /// <summary>
-            /// Enable or disable mouse support (Independent from controllers binding)
-            /// </summary>
-            public ReactiveObject<bool> EnableMouse { get; private set; }
-
-            /// <summary>
-            /// Hotkey Keyboard Bindings
-            /// </summary>
-            public ReactiveObject<KeyboardHotkeys> Hotkeys { get; private set; }
-
-            /// <summary>
-            /// Input device configuration.
-            /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed.
-            /// TODO: Implement a ReactiveList class.
-            /// </summary>
-            public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
-
-            public HidSection()
-            {
-                EnableKeyboard = new ReactiveObject<bool>();
-                EnableMouse = new ReactiveObject<bool>();
-                Hotkeys = new ReactiveObject<KeyboardHotkeys>();
-                InputConfig = new ReactiveObject<List<InputConfig>>();
-            }
-        }
-
-        /// <summary>
-        /// Graphics configuration section
-        /// </summary>
-        public class GraphicsSection
-        {
-            /// <summary>
-            /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime.
-            /// </summary>
-            public ReactiveObject<BackendThreading> BackendThreading { get; private set; }
-
-            /// <summary>
-            /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide.
-            /// </summary>
-            public ReactiveObject<float> MaxAnisotropy { get; private set; }
-
-            /// <summary>
-            /// Aspect Ratio applied to the renderer window.
-            /// </summary>
-            public ReactiveObject<AspectRatio> AspectRatio { get; private set; }
-
-            /// <summary>
-            /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead.
-            /// </summary>
-            public ReactiveObject<int> ResScale { get; private set; }
-
-            /// <summary>
-            /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.
-            /// </summary>
-            public ReactiveObject<float> ResScaleCustom { get; private set; }
-
-            /// <summary>
-            /// Dumps shaders in this local directory
-            /// </summary>
-            public ReactiveObject<string> ShadersDumpPath { get; private set; }
-
-            /// <summary>
-            /// Enables or disables Vertical Sync
-            /// </summary>
-            public ReactiveObject<bool> EnableVsync { get; private set; }
-
-            /// <summary>
-            /// Enables or disables Shader cache
-            /// </summary>
-            public ReactiveObject<bool> EnableShaderCache { get; private set; }
-
-            /// <summary>
-            /// Enables or disables texture recompression
-            /// </summary>
-            public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
-
-            /// <summary>
-            /// Enables or disables Macro high-level emulation
-            /// </summary>
-            public ReactiveObject<bool> EnableMacroHLE { get; private set; }
-
-            /// <summary>
-            /// Enables or disables color space passthrough, if available.
-            /// </summary>
-            public ReactiveObject<bool> EnableColorSpacePassthrough { get; private set; }
-
-            /// <summary>
-            /// Graphics backend
-            /// </summary>
-            public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; }
-
-            /// <summary>
-            /// Applies anti-aliasing to the renderer.
-            /// </summary>
-            public ReactiveObject<AntiAliasing> AntiAliasing { get; private set; }
-
-            /// <summary>
-            /// Sets the framebuffer upscaling type.
-            /// </summary>
-            public ReactiveObject<ScalingFilter> ScalingFilter { get; private set; }
-
-            /// <summary>
-            /// Sets the framebuffer upscaling level.
-            /// </summary>
-            public ReactiveObject<int> ScalingFilterLevel { get; private set; }
-
-            /// <summary>
-            /// Preferred GPU
-            /// </summary>
-            public ReactiveObject<string> PreferredGpu { get; private set; }
-
-            public GraphicsSection()
-            {
-                BackendThreading = new ReactiveObject<BackendThreading>();
-                BackendThreading.Event += static (sender, e) => LogValueChange(e, nameof(BackendThreading));
-                ResScale = new ReactiveObject<int>();
-                ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale));
-                ResScaleCustom = new ReactiveObject<float>();
-                ResScaleCustom.Event += static (sender, e) => LogValueChange(e, nameof(ResScaleCustom));
-                MaxAnisotropy = new ReactiveObject<float>();
-                MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy));
-                AspectRatio = new ReactiveObject<AspectRatio>();
-                AspectRatio.Event += static (sender, e) => LogValueChange(e, nameof(AspectRatio));
-                ShadersDumpPath = new ReactiveObject<string>();
-                EnableVsync = new ReactiveObject<bool>();
-                EnableVsync.Event += static (sender, e) => LogValueChange(e, nameof(EnableVsync));
-                EnableShaderCache = new ReactiveObject<bool>();
-                EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache));
-                EnableTextureRecompression = new ReactiveObject<bool>();
-                EnableTextureRecompression.Event += static (sender, e) => LogValueChange(e, nameof(EnableTextureRecompression));
-                GraphicsBackend = new ReactiveObject<GraphicsBackend>();
-                GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend));
-                PreferredGpu = new ReactiveObject<string>();
-                PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu));
-                EnableMacroHLE = new ReactiveObject<bool>();
-                EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE));
-                EnableColorSpacePassthrough = new ReactiveObject<bool>();
-                EnableColorSpacePassthrough.Event += static (sender, e) => LogValueChange(e, nameof(EnableColorSpacePassthrough));
-                AntiAliasing = new ReactiveObject<AntiAliasing>();
-                AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing));
-                ScalingFilter = new ReactiveObject<ScalingFilter>();
-                ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter));
-                ScalingFilterLevel = new ReactiveObject<int>();
-                ScalingFilterLevel.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilterLevel));
-            }
-        }
-
-        /// <summary>
-        /// Multiplayer configuration section
-        /// </summary>
-        public class MultiplayerSection
-        {
-            /// <summary>
-            /// GUID for the network interface used by LAN (or 0 for default)
-            /// </summary>
-            public ReactiveObject<string> LanInterfaceId { get; private set; }
-
-            /// <summary>
-            /// Multiplayer Mode
-            /// </summary>
-            public ReactiveObject<MultiplayerMode> Mode { get; private set; }
-
-            public MultiplayerSection()
-            {
-                LanInterfaceId = new ReactiveObject<string>();
-                Mode = new ReactiveObject<MultiplayerMode>();
-                Mode.Event += static (_, e) => LogValueChange(e, nameof(MultiplayerMode));
-            }
-        }
-
-        /// <summary>
-        /// The default configuration instance
-        /// </summary>
-        public static ConfigurationState Instance { get; private set; }
-
-        /// <summary>
-        /// The Ui section
-        /// </summary>
-        public UiSection Ui { get; private set; }
-
-        /// <summary>
-        /// The Logger section
-        /// </summary>
-        public LoggerSection Logger { get; private set; }
-
-        /// <summary>
-        /// The System section
-        /// </summary>
-        public SystemSection System { get; private set; }
-
-        /// <summary>
-        /// The Graphics section
-        /// </summary>
-        public GraphicsSection Graphics { get; private set; }
-
-        /// <summary>
-        /// The Hid section
-        /// </summary>
-        public HidSection Hid { get; private set; }
-
-        /// <summary>
-        /// The Multiplayer section
-        /// </summary>
-        public MultiplayerSection Multiplayer { get; private set; }
-
-        /// <summary>
-        /// Enables or disables Discord Rich Presence
-        /// </summary>
-        public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
-
-        /// <summary>
-        /// Checks for updates when Ryujinx starts when enabled
-        /// </summary>
-        public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
-
-        /// <summary>
-        /// Show "Confirm Exit" Dialog
-        /// </summary>
-        public ReactiveObject<bool> ShowConfirmExit { get; private set; }
-
-        /// <summary>
-        /// Hide Cursor on Idle
-        /// </summary>
-        public ReactiveObject<HideCursorMode> HideCursor { get; private set; }
-
-        private ConfigurationState()
-        {
-            Ui = new UiSection();
-            Logger = new LoggerSection();
-            System = new SystemSection();
-            Graphics = new GraphicsSection();
-            Hid = new HidSection();
-            Multiplayer = new MultiplayerSection();
-            EnableDiscordIntegration = new ReactiveObject<bool>();
-            CheckUpdatesOnStart = new ReactiveObject<bool>();
-            ShowConfirmExit = new ReactiveObject<bool>();
-            HideCursor = new ReactiveObject<HideCursorMode>();
-        }
-
-        public ConfigurationFileFormat ToFileFormat()
-        {
-            ConfigurationFileFormat configurationFile = new()
-            {
-                Version = ConfigurationFileFormat.CurrentVersion,
-                BackendThreading = Graphics.BackendThreading,
-                EnableFileLog = Logger.EnableFileLog,
-                ResScale = Graphics.ResScale,
-                ResScaleCustom = Graphics.ResScaleCustom,
-                MaxAnisotropy = Graphics.MaxAnisotropy,
-                AspectRatio = Graphics.AspectRatio,
-                AntiAliasing = Graphics.AntiAliasing,
-                ScalingFilter = Graphics.ScalingFilter,
-                ScalingFilterLevel = Graphics.ScalingFilterLevel,
-                GraphicsShadersDumpPath = Graphics.ShadersDumpPath,
-                LoggingEnableDebug = Logger.EnableDebug,
-                LoggingEnableStub = Logger.EnableStub,
-                LoggingEnableInfo = Logger.EnableInfo,
-                LoggingEnableWarn = Logger.EnableWarn,
-                LoggingEnableError = Logger.EnableError,
-                LoggingEnableTrace = Logger.EnableTrace,
-                LoggingEnableGuest = Logger.EnableGuest,
-                LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
-                LoggingFilteredClasses = Logger.FilteredClasses,
-                LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel,
-                SystemLanguage = System.Language,
-                SystemRegion = System.Region,
-                SystemTimeZone = System.TimeZone,
-                SystemTimeOffset = System.SystemTimeOffset,
-                DockedMode = System.EnableDockedMode,
-                EnableDiscordIntegration = EnableDiscordIntegration,
-                CheckUpdatesOnStart = CheckUpdatesOnStart,
-                ShowConfirmExit = ShowConfirmExit,
-                HideCursor = HideCursor,
-                EnableVsync = Graphics.EnableVsync,
-                EnableShaderCache = Graphics.EnableShaderCache,
-                EnableTextureRecompression = Graphics.EnableTextureRecompression,
-                EnableMacroHLE = Graphics.EnableMacroHLE,
-                EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough,
-                EnablePtc = System.EnablePtc,
-                EnableInternetAccess = System.EnableInternetAccess,
-                EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
-                FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
-                AudioBackend = System.AudioBackend,
-                AudioVolume = System.AudioVolume,
-                MemoryManagerMode = System.MemoryManagerMode,
-                ExpandRam = System.ExpandRam,
-                IgnoreMissingServices = System.IgnoreMissingServices,
-                UseHypervisor = System.UseHypervisor,
-                GuiColumns = new GuiColumns
-                {
-                    FavColumn = Ui.GuiColumns.FavColumn,
-                    IconColumn = Ui.GuiColumns.IconColumn,
-                    AppColumn = Ui.GuiColumns.AppColumn,
-                    DevColumn = Ui.GuiColumns.DevColumn,
-                    VersionColumn = Ui.GuiColumns.VersionColumn,
-                    TimePlayedColumn = Ui.GuiColumns.TimePlayedColumn,
-                    LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
-                    FileExtColumn = Ui.GuiColumns.FileExtColumn,
-                    FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
-                    PathColumn = Ui.GuiColumns.PathColumn,
-                },
-                ColumnSort = new ColumnSort
-                {
-                    SortColumnId = Ui.ColumnSort.SortColumnId,
-                    SortAscending = Ui.ColumnSort.SortAscending,
-                },
-                GameDirs = Ui.GameDirs,
-                ShownFileTypes = new ShownFileTypes
-                {
-                    NSP = Ui.ShownFileTypes.NSP,
-                    PFS0 = Ui.ShownFileTypes.PFS0,
-                    XCI = Ui.ShownFileTypes.XCI,
-                    NCA = Ui.ShownFileTypes.NCA,
-                    NRO = Ui.ShownFileTypes.NRO,
-                    NSO = Ui.ShownFileTypes.NSO,
-                },
-                WindowStartup = new WindowStartup
-                {
-                    WindowSizeWidth = Ui.WindowStartup.WindowSizeWidth,
-                    WindowSizeHeight = Ui.WindowStartup.WindowSizeHeight,
-                    WindowPositionX = Ui.WindowStartup.WindowPositionX,
-                    WindowPositionY = Ui.WindowStartup.WindowPositionY,
-                    WindowMaximized = Ui.WindowStartup.WindowMaximized,
-                },
-                LanguageCode = Ui.LanguageCode,
-                EnableCustomTheme = Ui.EnableCustomTheme,
-                CustomThemePath = Ui.CustomThemePath,
-                BaseStyle = Ui.BaseStyle,
-                GameListViewMode = Ui.GameListViewMode,
-                ShowNames = Ui.ShowNames,
-                GridSize = Ui.GridSize,
-                ApplicationSort = Ui.ApplicationSort,
-                IsAscendingOrder = Ui.IsAscendingOrder,
-                StartFullscreen = Ui.StartFullscreen,
-                ShowConsole = Ui.ShowConsole,
-                EnableKeyboard = Hid.EnableKeyboard,
-                EnableMouse = Hid.EnableMouse,
-                Hotkeys = Hid.Hotkeys,
-                KeyboardConfig = new List<JsonObject>(),
-                ControllerConfig = new List<JsonObject>(),
-                InputConfig = Hid.InputConfig,
-                GraphicsBackend = Graphics.GraphicsBackend,
-                PreferredGpu = Graphics.PreferredGpu,
-                MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
-                MultiplayerMode = Multiplayer.Mode,
-            };
-
-            return configurationFile;
-        }
-
-        public void LoadDefault()
-        {
-            Logger.EnableFileLog.Value = true;
-            Graphics.BackendThreading.Value = BackendThreading.Auto;
-            Graphics.ResScale.Value = 1;
-            Graphics.ResScaleCustom.Value = 1.0f;
-            Graphics.MaxAnisotropy.Value = -1.0f;
-            Graphics.AspectRatio.Value = AspectRatio.Fixed16x9;
-            Graphics.GraphicsBackend.Value = DefaultGraphicsBackend();
-            Graphics.PreferredGpu.Value = "";
-            Graphics.ShadersDumpPath.Value = "";
-            Logger.EnableDebug.Value = false;
-            Logger.EnableStub.Value = true;
-            Logger.EnableInfo.Value = true;
-            Logger.EnableWarn.Value = true;
-            Logger.EnableError.Value = true;
-            Logger.EnableTrace.Value = false;
-            Logger.EnableGuest.Value = true;
-            Logger.EnableFsAccessLog.Value = false;
-            Logger.FilteredClasses.Value = Array.Empty<LogClass>();
-            Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None;
-            System.Language.Value = Language.AmericanEnglish;
-            System.Region.Value = Region.USA;
-            System.TimeZone.Value = "UTC";
-            System.SystemTimeOffset.Value = 0;
-            System.EnableDockedMode.Value = true;
-            EnableDiscordIntegration.Value = true;
-            CheckUpdatesOnStart.Value = true;
-            ShowConfirmExit.Value = true;
-            HideCursor.Value = HideCursorMode.OnIdle;
-            Graphics.EnableVsync.Value = true;
-            Graphics.EnableShaderCache.Value = true;
-            Graphics.EnableTextureRecompression.Value = false;
-            Graphics.EnableMacroHLE.Value = true;
-            Graphics.EnableColorSpacePassthrough.Value = false;
-            Graphics.AntiAliasing.Value = AntiAliasing.None;
-            Graphics.ScalingFilter.Value = ScalingFilter.Bilinear;
-            Graphics.ScalingFilterLevel.Value = 80;
-            System.EnablePtc.Value = true;
-            System.EnableInternetAccess.Value = false;
-            System.EnableFsIntegrityChecks.Value = true;
-            System.FsGlobalAccessLogMode.Value = 0;
-            System.AudioBackend.Value = AudioBackend.SDL2;
-            System.AudioVolume.Value = 1;
-            System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
-            System.ExpandRam.Value = false;
-            System.IgnoreMissingServices.Value = false;
-            System.UseHypervisor.Value = true;
-            Multiplayer.LanInterfaceId.Value = "0";
-            Multiplayer.Mode.Value = MultiplayerMode.Disabled;
-            Ui.GuiColumns.FavColumn.Value = true;
-            Ui.GuiColumns.IconColumn.Value = true;
-            Ui.GuiColumns.AppColumn.Value = true;
-            Ui.GuiColumns.DevColumn.Value = true;
-            Ui.GuiColumns.VersionColumn.Value = true;
-            Ui.GuiColumns.TimePlayedColumn.Value = true;
-            Ui.GuiColumns.LastPlayedColumn.Value = true;
-            Ui.GuiColumns.FileExtColumn.Value = true;
-            Ui.GuiColumns.FileSizeColumn.Value = true;
-            Ui.GuiColumns.PathColumn.Value = true;
-            Ui.ColumnSort.SortColumnId.Value = 0;
-            Ui.ColumnSort.SortAscending.Value = false;
-            Ui.GameDirs.Value = new List<string>();
-            Ui.ShownFileTypes.NSP.Value = true;
-            Ui.ShownFileTypes.PFS0.Value = true;
-            Ui.ShownFileTypes.XCI.Value = true;
-            Ui.ShownFileTypes.NCA.Value = true;
-            Ui.ShownFileTypes.NRO.Value = true;
-            Ui.ShownFileTypes.NSO.Value = true;
-            Ui.EnableCustomTheme.Value = true;
-            Ui.LanguageCode.Value = "en_US";
-            Ui.CustomThemePath.Value = "";
-            Ui.BaseStyle.Value = "Dark";
-            Ui.GameListViewMode.Value = 0;
-            Ui.ShowNames.Value = true;
-            Ui.GridSize.Value = 2;
-            Ui.ApplicationSort.Value = 0;
-            Ui.IsAscendingOrder.Value = true;
-            Ui.StartFullscreen.Value = false;
-            Ui.ShowConsole.Value = true;
-            Ui.WindowStartup.WindowSizeWidth.Value = 1280;
-            Ui.WindowStartup.WindowSizeHeight.Value = 760;
-            Ui.WindowStartup.WindowPositionX.Value = 0;
-            Ui.WindowStartup.WindowPositionY.Value = 0;
-            Ui.WindowStartup.WindowMaximized.Value = false;
-            Hid.EnableKeyboard.Value = false;
-            Hid.EnableMouse.Value = false;
-            Hid.Hotkeys.Value = new KeyboardHotkeys
-            {
-                ToggleVsync = Key.F1,
-                ToggleMute = Key.F2,
-                Screenshot = Key.F8,
-                ShowUi = Key.F4,
-                Pause = Key.F5,
-                ResScaleUp = Key.Unbound,
-                ResScaleDown = Key.Unbound,
-                VolumeUp = Key.Unbound,
-                VolumeDown = Key.Unbound,
-            };
-            Hid.InputConfig.Value = new List<InputConfig>
-            {
-                new StandardKeyboardInputConfig
-                {
-                    Version = InputConfig.CurrentVersion,
-                    Backend = InputBackendType.WindowKeyboard,
-                    Id = "0",
-                    PlayerIndex = PlayerIndex.Player1,
-                    ControllerType = ControllerType.JoyconPair,
-                    LeftJoycon = new LeftJoyconCommonConfig<Key>
-                    {
-                        DpadUp = Key.Up,
-                        DpadDown = Key.Down,
-                        DpadLeft = Key.Left,
-                        DpadRight = Key.Right,
-                        ButtonMinus = Key.Minus,
-                        ButtonL = Key.E,
-                        ButtonZl = Key.Q,
-                        ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound,
-                    },
-                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
-                    {
-                        StickUp = Key.W,
-                        StickDown = Key.S,
-                        StickLeft = Key.A,
-                        StickRight = Key.D,
-                        StickButton = Key.F,
-                    },
-                    RightJoycon = new RightJoyconCommonConfig<Key>
-                    {
-                        ButtonA = Key.Z,
-                        ButtonB = Key.X,
-                        ButtonX = Key.C,
-                        ButtonY = Key.V,
-                        ButtonPlus = Key.Plus,
-                        ButtonR = Key.U,
-                        ButtonZr = Key.O,
-                        ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound,
-                    },
-                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                    {
-                        StickUp = Key.I,
-                        StickDown = Key.K,
-                        StickLeft = Key.J,
-                        StickRight = Key.L,
-                        StickButton = Key.H,
-                    },
-                },
-            };
-        }
-
-        public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
-        {
-            bool configurationFileUpdated = false;
-
-            if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
-
-                LoadDefault();
-            }
-
-            if (configurationFileFormat.Version < 2)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
-
-                configurationFileFormat.SystemRegion = Region.USA;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 3)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
-
-                configurationFileFormat.SystemTimeZone = "UTC";
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 4)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
-
-                configurationFileFormat.MaxAnisotropy = -1;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 5)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
-
-                configurationFileFormat.SystemTimeOffset = 0;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 8)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
-
-                configurationFileFormat.EnablePtc = true;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 9)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
-
-                configurationFileFormat.ColumnSort = new ColumnSort
-                {
-                    SortColumnId = 0,
-                    SortAscending = false,
-                };
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = Key.F1,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 10)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
-
-                configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 11)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
-
-                configurationFileFormat.ResScale = 1;
-                configurationFileFormat.ResScaleCustom = 1.0f;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 12)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
-
-                configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
-
-                configurationFileUpdated = true;
-            }
-
-            // configurationFileFormat.Version == 13 -> LDN1
-
-            if (configurationFileFormat.Version < 14)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
-
-                configurationFileFormat.CheckUpdatesOnStart = true;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 16)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
-
-                configurationFileFormat.EnableShaderCache = true;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 17)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
-
-                configurationFileFormat.StartFullscreen = false;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 18)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
-
-                configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
-
-                configurationFileUpdated = true;
-            }
-
-            // configurationFileFormat.Version == 19 -> LDN2
-
-            if (configurationFileFormat.Version < 20)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
-
-                configurationFileFormat.ShowConfirmExit = true;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 21)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21.");
-
-                // Initialize network config.
-
-                configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled;
-                configurationFileFormat.MultiplayerLanInterfaceId = "0";
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 22)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
-
-                configurationFileFormat.HideCursor = HideCursorMode.Never;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 24)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
-
-                configurationFileFormat.InputConfig = new List<InputConfig>
-                {
-                    new StandardKeyboardInputConfig
-                    {
-                        Version = InputConfig.CurrentVersion,
-                        Backend = InputBackendType.WindowKeyboard,
-                        Id = "0",
-                        PlayerIndex = PlayerIndex.Player1,
-                        ControllerType = ControllerType.JoyconPair,
-                        LeftJoycon = new LeftJoyconCommonConfig<Key>
-                        {
-                            DpadUp = Key.Up,
-                            DpadDown = Key.Down,
-                            DpadLeft = Key.Left,
-                            DpadRight = Key.Right,
-                            ButtonMinus = Key.Minus,
-                            ButtonL = Key.E,
-                            ButtonZl = Key.Q,
-                            ButtonSl = Key.Unbound,
-                            ButtonSr = Key.Unbound,
-                        },
-                        LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
-                        {
-                            StickUp = Key.W,
-                            StickDown = Key.S,
-                            StickLeft = Key.A,
-                            StickRight = Key.D,
-                            StickButton = Key.F,
-                        },
-                        RightJoycon = new RightJoyconCommonConfig<Key>
-                        {
-                            ButtonA = Key.Z,
-                            ButtonB = Key.X,
-                            ButtonX = Key.C,
-                            ButtonY = Key.V,
-                            ButtonPlus = Key.Plus,
-                            ButtonR = Key.U,
-                            ButtonZr = Key.O,
-                            ButtonSl = Key.Unbound,
-                            ButtonSr = Key.Unbound,
-                        },
-                        RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                        {
-                            StickUp = Key.I,
-                            StickDown = Key.K,
-                            StickLeft = Key.J,
-                            StickRight = Key.L,
-                            StickButton = Key.H,
-                        },
-                    },
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 25)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 26)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
-
-                configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 27)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
-
-                configurationFileFormat.EnableMouse = false;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 28)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = Key.F1,
-                    Screenshot = Key.F8,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 29)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = Key.F1,
-                    Screenshot = Key.F8,
-                    ShowUi = Key.F4,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 30)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
-
-                foreach (InputConfig config in configurationFileFormat.InputConfig)
-                {
-                    if (config is StandardControllerInputConfig controllerConfig)
-                    {
-                        controllerConfig.Rumble = new RumbleConfigController
-                        {
-                            EnableRumble = false,
-                            StrongRumble = 1f,
-                            WeakRumble = 1f,
-                        };
-                    }
-                }
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 31)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
-
-                configurationFileFormat.BackendThreading = BackendThreading.Auto;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 32)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
-                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
-                    ShowUi = configurationFileFormat.Hotkeys.ShowUi,
-                    Pause = Key.F5,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 33)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
-                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
-                    ShowUi = configurationFileFormat.Hotkeys.ShowUi,
-                    Pause = configurationFileFormat.Hotkeys.Pause,
-                    ToggleMute = Key.F2,
-                };
-
-                configurationFileFormat.AudioVolume = 1;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 34)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
-
-                configurationFileFormat.EnableInternetAccess = false;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 35)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
-
-                foreach (InputConfig config in configurationFileFormat.InputConfig)
-                {
-                    if (config is StandardControllerInputConfig controllerConfig)
-                    {
-                        controllerConfig.RangeLeft = 1.0f;
-                        controllerConfig.RangeRight = 1.0f;
-                    }
-                }
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 36)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
-
-                configurationFileFormat.LoggingEnableTrace = false;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 37)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
-
-                configurationFileFormat.ShowConsole = true;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 38)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38.");
-
-                configurationFileFormat.BaseStyle = "Dark";
-                configurationFileFormat.GameListViewMode = 0;
-                configurationFileFormat.ShowNames = true;
-                configurationFileFormat.GridSize = 2;
-                configurationFileFormat.LanguageCode = "en_US";
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 39)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
-                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
-                    ShowUi = configurationFileFormat.Hotkeys.ShowUi,
-                    Pause = configurationFileFormat.Hotkeys.Pause,
-                    ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
-                    ResScaleUp = Key.Unbound,
-                    ResScaleDown = Key.Unbound,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 40)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40.");
-
-                configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 41)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41.");
-
-                configurationFileFormat.Hotkeys = new KeyboardHotkeys
-                {
-                    ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
-                    Screenshot = configurationFileFormat.Hotkeys.Screenshot,
-                    ShowUi = configurationFileFormat.Hotkeys.ShowUi,
-                    Pause = configurationFileFormat.Hotkeys.Pause,
-                    ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
-                    ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
-                    ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
-                    VolumeUp = Key.Unbound,
-                    VolumeDown = Key.Unbound,
-                };
-            }
-
-            if (configurationFileFormat.Version < 42)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
-
-                configurationFileFormat.EnableMacroHLE = true;
-            }
-
-            if (configurationFileFormat.Version < 43)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43.");
-
-                configurationFileFormat.UseHypervisor = true;
-            }
-
-            if (configurationFileFormat.Version < 44)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44.");
-
-                configurationFileFormat.AntiAliasing = AntiAliasing.None;
-                configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear;
-                configurationFileFormat.ScalingFilterLevel = 80;
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 45)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
-
-                configurationFileFormat.ShownFileTypes = new ShownFileTypes
-                {
-                    NSP = true,
-                    PFS0 = true,
-                    XCI = true,
-                    NCA = true,
-                    NRO = true,
-                    NSO = true,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 46)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
-
-                configurationFileFormat.MultiplayerLanInterfaceId = "0";
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 47)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
-
-                configurationFileFormat.WindowStartup = new WindowStartup
-                {
-                    WindowPositionX = 0,
-                    WindowPositionY = 0,
-                    WindowSizeHeight = 760,
-                    WindowSizeWidth = 1280,
-                    WindowMaximized = false,
-                };
-
-                configurationFileUpdated = true;
-            }
-
-            if (configurationFileFormat.Version < 48)
-            {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
-
-                configurationFileFormat.EnableColorSpacePassthrough = false;
-
-                configurationFileUpdated = true;
-            }
-
-            Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
-            Graphics.ResScale.Value = configurationFileFormat.ResScale;
-            Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
-            Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
-            Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
-            Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
-            Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
-            Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend;
-            Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu;
-            Graphics.AntiAliasing.Value = configurationFileFormat.AntiAliasing;
-            Graphics.ScalingFilter.Value = configurationFileFormat.ScalingFilter;
-            Graphics.ScalingFilterLevel.Value = configurationFileFormat.ScalingFilterLevel;
-            Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
-            Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
-            Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
-            Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
-            Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
-            Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
-            Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
-            Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
-            Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
-            Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
-            System.Language.Value = configurationFileFormat.SystemLanguage;
-            System.Region.Value = configurationFileFormat.SystemRegion;
-            System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
-            System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
-            System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
-            EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
-            CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
-            ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
-            HideCursor.Value = configurationFileFormat.HideCursor;
-            Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
-            Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
-            Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
-            Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
-            Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
-            System.EnablePtc.Value = configurationFileFormat.EnablePtc;
-            System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
-            System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
-            System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
-            System.AudioBackend.Value = configurationFileFormat.AudioBackend;
-            System.AudioVolume.Value = configurationFileFormat.AudioVolume;
-            System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
-            System.ExpandRam.Value = configurationFileFormat.ExpandRam;
-            System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
-            System.UseHypervisor.Value = configurationFileFormat.UseHypervisor;
-            Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
-            Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
-            Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
-            Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
-            Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
-            Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
-            Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
-            Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
-            Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
-            Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
-            Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
-            Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
-            Ui.GameDirs.Value = configurationFileFormat.GameDirs;
-            Ui.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP;
-            Ui.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0;
-            Ui.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI;
-            Ui.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA;
-            Ui.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO;
-            Ui.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO;
-            Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
-            Ui.LanguageCode.Value = configurationFileFormat.LanguageCode;
-            Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
-            Ui.BaseStyle.Value = configurationFileFormat.BaseStyle;
-            Ui.GameListViewMode.Value = configurationFileFormat.GameListViewMode;
-            Ui.ShowNames.Value = configurationFileFormat.ShowNames;
-            Ui.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder;
-            Ui.GridSize.Value = configurationFileFormat.GridSize;
-            Ui.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
-            Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
-            Ui.ShowConsole.Value = configurationFileFormat.ShowConsole;
-            Ui.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth;
-            Ui.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight;
-            Ui.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX;
-            Ui.WindowStartup.WindowPositionY.Value = configurationFileFormat.WindowStartup.WindowPositionY;
-            Ui.WindowStartup.WindowMaximized.Value = configurationFileFormat.WindowStartup.WindowMaximized;
-            Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
-            Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
-            Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
-            Hid.InputConfig.Value = configurationFileFormat.InputConfig;
-
-            if (Hid.InputConfig.Value == null)
-            {
-                Hid.InputConfig.Value = new List<InputConfig>();
-            }
-
-            Multiplayer.LanInterfaceId.Value = configurationFileFormat.MultiplayerLanInterfaceId;
-            Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
-
-            if (configurationFileUpdated)
-            {
-                ToFileFormat().SaveConfig(configurationFilePath);
-
-                Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
-            }
-        }
-
-        private static GraphicsBackend DefaultGraphicsBackend()
-        {
-            // Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
-            // Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
-            if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
-            {
-                return GraphicsBackend.Vulkan;
-            }
-
-            return GraphicsBackend.OpenGl;
-        }
-
-        private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName)
-        {
-            Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
-        }
-
-        public static void Initialize()
-        {
-            if (Instance != null)
-            {
-                throw new InvalidOperationException("Configuration is already initialized");
-            }
-
-            Instance = new ConfigurationState();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/FileTypes.cs b/src/Ryujinx.Ui.Common/Configuration/FileTypes.cs
deleted file mode 100644
index 9d2f6386..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/FileTypes.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.Ui.Common
-{
-    public enum FileTypes
-    {
-        NSP,
-        PFS0,
-        XCI,
-        NCA,
-        NRO,
-        NSO
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs b/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs
deleted file mode 100644
index 2edcd07f..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Logging.Targets;
-using System;
-using System.IO;
-
-namespace Ryujinx.Ui.Common.Configuration
-{
-    public static class LoggerModule
-    {
-        public static void Initialize()
-        {
-            ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug;
-            ConfigurationState.Instance.Logger.EnableStub.Event += ReloadEnableStub;
-            ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo;
-            ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning;
-            ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError;
-            ConfigurationState.Instance.Logger.EnableTrace.Event += ReloadEnableTrace;
-            ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest;
-            ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog;
-            ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses;
-            ConfigurationState.Instance.Logger.EnableFileLog.Event += ReloadFileLogger;
-        }
-
-        private static void ReloadEnableDebug(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Debug, e.NewValue);
-        }
-
-        private static void ReloadEnableStub(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Stub, e.NewValue);
-        }
-
-        private static void ReloadEnableInfo(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Info, e.NewValue);
-        }
-
-        private static void ReloadEnableWarning(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Warning, e.NewValue);
-        }
-
-        private static void ReloadEnableError(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Error, e.NewValue);
-        }
-
-        private static void ReloadEnableTrace(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Trace, e.NewValue);
-        }
-
-        private static void ReloadEnableGuest(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.Guest, e.NewValue);
-        }
-
-        private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs<bool> e)
-        {
-            Logger.SetEnable(LogLevel.AccessLog, e.NewValue);
-        }
-
-        private static void ReloadFilteredClasses(object sender, ReactiveEventArgs<LogClass[]> e)
-        {
-            bool noFilter = e.NewValue.Length == 0;
-
-            foreach (var logClass in Enum.GetValues<LogClass>())
-            {
-                Logger.SetEnable(logClass, noFilter);
-            }
-
-            foreach (var logClass in e.NewValue)
-            {
-                Logger.SetEnable(logClass, true);
-            }
-        }
-
-        private static void ReloadFileLogger(object sender, ReactiveEventArgs<bool> e)
-        {
-            if (e.NewValue)
-            {
-                string logDir = AppDataManager.LogsDirPath;
-                FileStream logFile = null;
-
-                if (!string.IsNullOrEmpty(logDir))
-                {
-                    logFile = FileLogTarget.PrepareLogFile(logDir);
-                }
-
-                if (logFile == null)
-                {
-                    Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable.");
-                    Logger.RemoveTarget("file");
-
-                    return;
-                }
-
-                Logger.AddTarget(new AsyncLogTargetWrapper(
-                    new FileLogTarget("file", logFile),
-                    1000,
-                    AsyncLogTargetOverflowAction.Block
-                ));
-            }
-            else
-            {
-                Logger.RemoveTarget("file");
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/System/Language.cs b/src/Ryujinx.Ui.Common/Configuration/System/Language.cs
deleted file mode 100644
index 72416bfe..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/System/Language.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Ryujinx.Common.Utilities;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Configuration.System
-{
-    [JsonConverter(typeof(TypedStringEnumConverter<Language>))]
-    public enum Language
-    {
-        Japanese,
-        AmericanEnglish,
-        French,
-        German,
-        Italian,
-        Spanish,
-        Chinese,
-        Korean,
-        Dutch,
-        Portuguese,
-        Russian,
-        Taiwanese,
-        BritishEnglish,
-        CanadianFrench,
-        LatinAmericanSpanish,
-        SimplifiedChinese,
-        TraditionalChinese,
-        BrazilianPortuguese,
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/System/Region.cs b/src/Ryujinx.Ui.Common/Configuration/System/Region.cs
deleted file mode 100644
index 2478b40f..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/System/Region.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Ryujinx.Common.Utilities;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Configuration.System
-{
-    [JsonConverter(typeof(TypedStringEnumConverter<Region>))]
-    public enum Region
-    {
-        Japan,
-        USA,
-        Europe,
-        Australia,
-        China,
-        Korea,
-        Taiwan,
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/Ui/ColumnSort.cs b/src/Ryujinx.Ui.Common/Configuration/Ui/ColumnSort.cs
deleted file mode 100644
index 88cf7cda..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/Ui/ColumnSort.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Ryujinx.Ui.Common.Configuration.Ui
-{
-    public struct ColumnSort
-    {
-        public int SortColumnId { get; set; }
-        public bool SortAscending { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/Ui/GuiColumns.cs b/src/Ryujinx.Ui.Common/Configuration/Ui/GuiColumns.cs
deleted file mode 100644
index 7e944015..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/Ui/GuiColumns.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Ryujinx.Ui.Common.Configuration.Ui
-{
-    public struct GuiColumns
-    {
-        public bool FavColumn { get; set; }
-        public bool IconColumn { get; set; }
-        public bool AppColumn { get; set; }
-        public bool DevColumn { get; set; }
-        public bool VersionColumn { get; set; }
-        public bool TimePlayedColumn { get; set; }
-        public bool LastPlayedColumn { get; set; }
-        public bool FileExtColumn { get; set; }
-        public bool FileSizeColumn { get; set; }
-        public bool PathColumn { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs b/src/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs
deleted file mode 100644
index 1b14fd46..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.Ui.Common.Configuration.Ui
-{
-    public struct ShownFileTypes
-    {
-        public bool NSP { get; set; }
-        public bool PFS0 { get; set; }
-        public bool XCI { get; set; }
-        public bool NCA { get; set; }
-        public bool NRO { get; set; }
-        public bool NSO { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Configuration/Ui/WindowStartup.cs b/src/Ryujinx.Ui.Common/Configuration/Ui/WindowStartup.cs
deleted file mode 100644
index ce0dde6a..00000000
--- a/src/Ryujinx.Ui.Common/Configuration/Ui/WindowStartup.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Ryujinx.Ui.Common.Configuration.Ui
-{
-    public struct WindowStartup
-    {
-        public int WindowSizeWidth { get; set; }
-        public int WindowSizeHeight { get; set; }
-        public int WindowPositionX { get; set; }
-        public int WindowPositionY { get; set; }
-        public bool WindowMaximized { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/DiscordIntegrationModule.cs b/src/Ryujinx.Ui.Common/DiscordIntegrationModule.cs
deleted file mode 100644
index edc634aa..00000000
--- a/src/Ryujinx.Ui.Common/DiscordIntegrationModule.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using DiscordRPC;
-using Ryujinx.Common;
-using Ryujinx.Ui.Common.Configuration;
-
-namespace Ryujinx.Ui.Common
-{
-    public static class DiscordIntegrationModule
-    {
-        private const string Description = "A simple, experimental Nintendo Switch emulator.";
-        private const string CliendId = "568815339807309834";
-
-        private static DiscordRpcClient _discordClient;
-        private static RichPresence _discordPresenceMain;
-
-        public static void Initialize()
-        {
-            _discordPresenceMain = new RichPresence
-            {
-                Assets = new Assets
-                {
-                    LargeImageKey = "ryujinx",
-                    LargeImageText = Description,
-                },
-                Details = "Main Menu",
-                State = "Idling",
-                Timestamps = Timestamps.Now,
-                Buttons = new[]
-                {
-                    new Button
-                    {
-                        Label = "Website",
-                        Url   = "https://ryujinx.org/",
-                    },
-                },
-            };
-
-            ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
-        }
-
-        private static void Update(object sender, ReactiveEventArgs<bool> evnt)
-        {
-            if (evnt.OldValue != evnt.NewValue)
-            {
-                // If the integration was active, disable it and unload everything
-                if (evnt.OldValue)
-                {
-                    _discordClient?.Dispose();
-
-                    _discordClient = null;
-                }
-
-                // If we need to activate it and the client isn't active, initialize it
-                if (evnt.NewValue && _discordClient == null)
-                {
-                    _discordClient = new DiscordRpcClient(CliendId);
-
-                    _discordClient.Initialize();
-                    _discordClient.SetPresence(_discordPresenceMain);
-                }
-            }
-        }
-
-        public static void SwitchToPlayingState(string titleId, string titleName)
-        {
-            _discordClient?.SetPresence(new RichPresence
-            {
-                Assets = new Assets
-                {
-                    LargeImageKey = "game",
-                    LargeImageText = titleName,
-                    SmallImageKey = "ryujinx",
-                    SmallImageText = Description,
-                },
-                Details = $"Playing {titleName}",
-                State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(),
-                Timestamps = Timestamps.Now,
-                Buttons = new[]
-                {
-                    new Button
-                    {
-                        Label = "Website",
-                        Url = "https://ryujinx.org/",
-                    },
-                },
-            });
-        }
-
-        public static void SwitchToMainMenu()
-        {
-            _discordClient?.SetPresence(_discordPresenceMain);
-        }
-
-        public static void Exit()
-        {
-            _discordClient?.Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs b/src/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs
deleted file mode 100644
index c827f750..00000000
--- a/src/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using static Ryujinx.Ui.Common.Configuration.ConfigurationState.UiSection;
-
-namespace Ryujinx.Ui.Common
-{
-    public static class FileTypesExtensions
-    {
-        /// <summary>
-        /// Gets the current <see cref="ShownFileTypeSettings"/> value for the correlating FileType name.
-        /// </summary>
-        /// <param name="type">The name of the <see cref="ShownFileTypeSettings"/> parameter to get the value of.</param>
-        /// <param name="config">The config instance to get the value from.</param>
-        /// <returns>The current value of the setting. Value is <see langword="true"/> if the file type is the be shown on the games list, <see langword="false"/> otherwise.</returns>
-        public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch
-        {
-            FileTypes.NSP => config.NSP.Value,
-            FileTypes.PFS0 => config.PFS0.Value,
-            FileTypes.XCI => config.XCI.Value,
-            FileTypes.NCA => config.NCA.Value,
-            FileTypes.NRO => config.NRO.Value,
-            FileTypes.NSO => config.NSO.Value,
-            _ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
-        };
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/CommandLineState.cs b/src/Ryujinx.Ui.Common/Helper/CommandLineState.cs
deleted file mode 100644
index 714cf2f0..00000000
--- a/src/Ryujinx.Ui.Common/Helper/CommandLineState.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using Ryujinx.Common.Logging;
-using System.Collections.Generic;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static class CommandLineState
-    {
-        public static string[] Arguments { get; private set; }
-
-        public static bool? OverrideDockedMode { get; private set; }
-        public static string OverrideGraphicsBackend { get; private set; }
-        public static string OverrideHideCursor { get; private set; }
-        public static string BaseDirPathArg { get; private set; }
-        public static string Profile { get; private set; }
-        public static string LaunchPathArg { get; private set; }
-        public static bool StartFullscreenArg { get; private set; }
-
-        public static void ParseArguments(string[] args)
-        {
-            List<string> arguments = new();
-
-            // Parse Arguments.
-            for (int i = 0; i < args.Length; ++i)
-            {
-                string arg = args[i];
-
-                switch (arg)
-                {
-                    case "-r":
-                    case "--root-data-dir":
-                        if (i + 1 >= args.Length)
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
-
-                            continue;
-                        }
-
-                        BaseDirPathArg = args[++i];
-
-                        arguments.Add(arg);
-                        arguments.Add(args[i]);
-                        break;
-                    case "-p":
-                    case "--profile":
-                        if (i + 1 >= args.Length)
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
-
-                            continue;
-                        }
-
-                        Profile = args[++i];
-
-                        arguments.Add(arg);
-                        arguments.Add(args[i]);
-                        break;
-                    case "-f":
-                    case "--fullscreen":
-                        StartFullscreenArg = true;
-
-                        arguments.Add(arg);
-                        break;
-                    case "-g":
-                    case "--graphics-backend":
-                        if (i + 1 >= args.Length)
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
-
-                            continue;
-                        }
-
-                        OverrideGraphicsBackend = args[++i];
-                        break;
-                    case "--docked-mode":
-                        OverrideDockedMode = true;
-                        break;
-                    case "--handheld-mode":
-                        OverrideDockedMode = false;
-                        break;
-                    case "--hide-cursor":
-                        if (i + 1 >= args.Length)
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
-
-                            continue;
-                        }
-
-                        OverrideHideCursor = args[++i];
-                        break;
-                    default:
-                        LaunchPathArg = arg;
-                        break;
-                }
-            }
-
-            Arguments = arguments.ToArray();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/ConsoleHelper.cs b/src/Ryujinx.Ui.Common/Helper/ConsoleHelper.cs
deleted file mode 100644
index 65155641..00000000
--- a/src/Ryujinx.Ui.Common/Helper/ConsoleHelper.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static partial class ConsoleHelper
-    {
-        public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
-
-        public static void SetConsoleWindowState(bool show)
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                SetConsoleWindowStateWindows(show);
-            }
-            else if (show == false)
-            {
-                Logger.Warning?.Print(LogClass.Application, "OS doesn't support hiding console window");
-            }
-        }
-
-        [SupportedOSPlatform("windows")]
-        private static void SetConsoleWindowStateWindows(bool show)
-        {
-            const int SW_HIDE = 0;
-            const int SW_SHOW = 5;
-
-            IntPtr hWnd = GetConsoleWindow();
-
-            if (hWnd == IntPtr.Zero)
-            {
-                Logger.Warning?.Print(LogClass.Application, "Attempted to show/hide console window but console window does not exist");
-                return;
-            }
-
-            ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
-        }
-
-        [SupportedOSPlatform("windows")]
-        [LibraryImport("kernel32")]
-        private static partial IntPtr GetConsoleWindow();
-
-        [SupportedOSPlatform("windows")]
-        [LibraryImport("user32")]
-        [return: MarshalAs(UnmanagedType.Bool)]
-        private static partial bool ShowWindow(IntPtr hWnd, int nCmdShow);
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs
deleted file mode 100644
index daa59d25..00000000
--- a/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs
+++ /dev/null
@@ -1,202 +0,0 @@
-using Microsoft.Win32;
-using Ryujinx.Common;
-using Ryujinx.Common.Logging;
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static partial class FileAssociationHelper
-    {
-        private static readonly string[] _fileExtensions = { ".nca", ".nro", ".nso", ".nsp", ".xci" };
-
-        [SupportedOSPlatform("linux")]
-        private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
-
-        private const int SHCNE_ASSOCCHANGED = 0x8000000;
-        private const int SHCNF_FLUSH = 0x1000;
-
-        [LibraryImport("shell32.dll", SetLastError = true)]
-        public static partial void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
-
-        public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild;
-
-        [SupportedOSPlatform("linux")]
-        private static bool AreMimeTypesRegisteredLinux() => File.Exists(Path.Combine(_mimeDbPath, "packages", "Ryujinx.xml"));
-
-        [SupportedOSPlatform("linux")]
-        private static bool InstallLinuxMimeTypes(bool uninstall = false)
-        {
-            string installKeyword = uninstall ? "uninstall" : "install";
-
-            if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux()))
-            {
-                string mimeTypesFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mime", "Ryujinx.xml");
-                string additionalArgs = !uninstall ? "--novendor" : "";
-
-                using Process mimeProcess = new();
-
-                mimeProcess.StartInfo.FileName = "xdg-mime";
-                mimeProcess.StartInfo.Arguments = $"{installKeyword} {additionalArgs} --mode user {mimeTypesFile}";
-
-                mimeProcess.Start();
-                mimeProcess.WaitForExit();
-
-                if (mimeProcess.ExitCode != 0)
-                {
-                    Logger.Error?.PrintMsg(LogClass.Application, $"Unable to {installKeyword} mime types. Make sure xdg-utils is installed. Process exited with code: {mimeProcess.ExitCode}");
-
-                    return false;
-                }
-
-                using Process updateMimeProcess = new();
-
-                updateMimeProcess.StartInfo.FileName = "update-mime-database";
-                updateMimeProcess.StartInfo.Arguments = _mimeDbPath;
-
-                updateMimeProcess.Start();
-                updateMimeProcess.WaitForExit();
-
-                if (updateMimeProcess.ExitCode != 0)
-                {
-                    Logger.Error?.PrintMsg(LogClass.Application, $"Could not update local mime database. Process exited with code: {updateMimeProcess.ExitCode}");
-                }
-            }
-
-            return true;
-        }
-
-        [SupportedOSPlatform("windows")]
-        private static bool AreMimeTypesRegisteredWindows()
-        {
-            static bool CheckRegistering(string ext)
-            {
-                RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}");
-
-                if (key is null)
-                {
-                    return false;
-                }
-
-                var openCmd = key.OpenSubKey(@"shell\open\command");
-
-                string keyValue = (string)openCmd.GetValue("");
-
-                return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
-            }
-
-            bool registered = false;
-
-            foreach (string ext in _fileExtensions)
-            {
-                registered |= CheckRegistering(ext);
-            }
-
-            return registered;
-        }
-
-        [SupportedOSPlatform("windows")]
-        private static bool InstallWindowsMimeTypes(bool uninstall = false)
-        {
-            static bool RegisterExtension(string ext, bool uninstall = false)
-            {
-                string keyString = @$"Software\Classes\{ext}";
-
-                if (uninstall)
-                {
-                    // If the types don't already exist, there's nothing to do and we can call this operation successful.
-                    if (!AreMimeTypesRegisteredWindows())
-                    {
-                        return true;
-                    }
-                    Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
-                    Registry.CurrentUser.DeleteSubKeyTree(keyString);
-                    Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
-                }
-                else
-                {
-                    using var key = Registry.CurrentUser.CreateSubKey(keyString);
-
-                    if (key is null)
-                    {
-                        return false;
-                    }
-
-                    Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
-                    using var openCmd = key.CreateSubKey(@"shell\open\command");
-                    openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
-                    Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
-
-                }
-
-                return true;
-            }
-
-            bool registered = false;
-
-            foreach (string ext in _fileExtensions)
-            {
-                registered |= RegisterExtension(ext, uninstall);
-            }
-
-            // Notify Explorer the file association has been changed.
-            SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
-
-            return registered;
-        }
-
-        public static bool AreMimeTypesRegistered()
-        {
-            if (OperatingSystem.IsLinux())
-            {
-                return AreMimeTypesRegisteredLinux();
-            }
-
-            if (OperatingSystem.IsWindows())
-            {
-                return AreMimeTypesRegisteredWindows();
-            }
-
-            // TODO: Add macOS support.
-
-            return false;
-        }
-
-        public static bool Install()
-        {
-            if (OperatingSystem.IsLinux())
-            {
-                return InstallLinuxMimeTypes();
-            }
-
-            if (OperatingSystem.IsWindows())
-            {
-                return InstallWindowsMimeTypes();
-            }
-
-            // TODO: Add macOS support.
-
-            return false;
-        }
-
-        public static bool Uninstall()
-        {
-            if (OperatingSystem.IsLinux())
-            {
-                return InstallLinuxMimeTypes(true);
-            }
-
-            if (OperatingSystem.IsWindows())
-            {
-                return InstallWindowsMimeTypes(true);
-            }
-
-            // TODO: Add macOS support.
-
-            return false;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs b/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs
deleted file mode 100644
index bf647719..00000000
--- a/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    [SupportedOSPlatform("linux")]
-    public static class LinuxHelper
-    {
-        // NOTE: This value was determined by manual tests and might need to be increased again.
-        public const int RecommendedVmMaxMapCount = 524288;
-        public const string VmMaxMapCountPath = "/proc/sys/vm/max_map_count";
-        public const string SysCtlConfigPath = "/etc/sysctl.d/99-Ryujinx.conf";
-        public static int VmMaxMapCount => int.Parse(File.ReadAllText(VmMaxMapCountPath));
-        public static string PkExecPath { get; } = GetBinaryPath("pkexec");
-
-        private static string GetBinaryPath(string binary)
-        {
-            string pathVar = Environment.GetEnvironmentVariable("PATH");
-
-            if (pathVar is null || string.IsNullOrEmpty(binary))
-            {
-                return null;
-            }
-
-            foreach (var searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
-            {
-                string binaryPath = Path.Combine(searchPath, binary);
-
-                if (File.Exists(binaryPath))
-                {
-                    return binaryPath;
-                }
-            }
-
-            return null;
-        }
-
-        public static int RunPkExec(string command)
-        {
-            if (PkExecPath == null)
-            {
-                return 1;
-            }
-
-            using Process process = new()
-            {
-                StartInfo =
-                {
-                    FileName = PkExecPath,
-                    ArgumentList = { "sh", "-c", command },
-                },
-            };
-
-            process.Start();
-            process.WaitForExit();
-
-            return process.ExitCode;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs b/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
deleted file mode 100644
index af8723e2..00000000
--- a/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    [SupportedOSPlatform("macos")]
-    public static partial class ObjectiveC
-    {
-        private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
-
-        [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
-        private static partial IntPtr sel_getUid(string name);
-
-        [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
-        private static partial IntPtr objc_getClass(string name);
-
-        [LibraryImport(ObjCRuntime)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector);
-
-        [LibraryImport(ObjCRuntime)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
-
-        [LibraryImport(ObjCRuntime)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
-
-        [LibraryImport(ObjCRuntime)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
-
-        [LibraryImport(ObjCRuntime)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
-
-        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
-        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
-
-        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
-        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
-
-        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
-        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
-
-        [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
-        [return: MarshalAs(UnmanagedType.Bool)]
-        private static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
-
-        public readonly struct Object
-        {
-            public readonly IntPtr ObjPtr;
-
-            private Object(IntPtr pointer)
-            {
-                ObjPtr = pointer;
-            }
-
-            public Object(string name)
-            {
-                ObjPtr = objc_getClass(name);
-            }
-
-            public void SendMessage(Selector selector)
-            {
-                objc_msgSend(ObjPtr, selector);
-            }
-
-            public void SendMessage(Selector selector, byte value)
-            {
-                objc_msgSend(ObjPtr, selector, value);
-            }
-
-            public void SendMessage(Selector selector, Object obj)
-            {
-                objc_msgSend(ObjPtr, selector, obj.ObjPtr);
-            }
-
-            public void SendMessage(Selector selector, NSRect point)
-            {
-                objc_msgSend(ObjPtr, selector, point);
-            }
-
-            public void SendMessage(Selector selector, double value)
-            {
-                objc_msgSend(ObjPtr, selector, value);
-            }
-
-            public Object GetFromMessage(Selector selector)
-            {
-                return new Object(IntPtr_objc_msgSend(ObjPtr, selector));
-            }
-
-            public Object GetFromMessage(Selector selector, Object obj)
-            {
-                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, obj.ObjPtr));
-            }
-
-            public Object GetFromMessage(Selector selector, NSString nsString)
-            {
-                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, nsString.StrPtr));
-            }
-
-            public Object GetFromMessage(Selector selector, string param)
-            {
-                return new Object(IntPtr_objc_msgSend(ObjPtr, selector, param));
-            }
-
-            public bool GetBoolFromMessage(Selector selector, Object obj)
-            {
-                return bool_objc_msgSend(ObjPtr, selector, obj.ObjPtr);
-            }
-        }
-
-        public readonly struct Selector
-        {
-            public readonly IntPtr SelPtr;
-
-            private Selector(string name)
-            {
-                SelPtr = sel_getUid(name);
-            }
-
-            public static implicit operator Selector(string value) => new(value);
-        }
-
-        public readonly struct NSString
-        {
-            public readonly IntPtr StrPtr;
-
-            public NSString(string aString)
-            {
-                IntPtr nsString = objc_getClass("NSString");
-                StrPtr = IntPtr_objc_msgSend(nsString, "stringWithUTF8String:", aString);
-            }
-
-            public static implicit operator IntPtr(NSString nsString) => nsString.StrPtr;
-        }
-
-        public readonly struct NSPoint
-        {
-            public readonly double X;
-            public readonly double Y;
-
-            public NSPoint(double x, double y)
-            {
-                X = x;
-                Y = y;
-            }
-        }
-
-        public readonly struct NSRect
-        {
-            public readonly NSPoint Pos;
-            public readonly NSPoint Size;
-
-            public NSRect(double x, double y, double width, double height)
-            {
-                Pos = new NSPoint(x, y);
-                Size = new NSPoint(width, height);
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/OpenHelper.cs b/src/Ryujinx.Ui.Common/Helper/OpenHelper.cs
deleted file mode 100644
index 04ebbf3b..00000000
--- a/src/Ryujinx.Ui.Common/Helper/OpenHelper.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static partial class OpenHelper
-    {
-        [LibraryImport("shell32.dll", SetLastError = true)]
-        private static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
-
-        [LibraryImport("shell32.dll", SetLastError = true)]
-        private static partial void ILFree(IntPtr pidlList);
-
-        [LibraryImport("shell32.dll", SetLastError = true)]
-        private static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath);
-
-        public static void OpenFolder(string path)
-        {
-            if (Directory.Exists(path))
-            {
-                Process.Start(new ProcessStartInfo
-                {
-                    FileName = path,
-                    UseShellExecute = true,
-                    Verb = "open",
-                });
-            }
-            else
-            {
-                Logger.Notice.Print(LogClass.Application, $"Directory \"{path}\" doesn't exist!");
-            }
-        }
-
-        public static void LocateFile(string path)
-        {
-            if (File.Exists(path))
-            {
-                if (OperatingSystem.IsWindows())
-                {
-                    IntPtr pidlList = ILCreateFromPathW(path);
-                    if (pidlList != IntPtr.Zero)
-                    {
-                        try
-                        {
-                            Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0));
-                        }
-                        finally
-                        {
-                            ILFree(pidlList);
-                        }
-                    }
-                }
-                else if (OperatingSystem.IsMacOS())
-                {
-                    ObjectiveC.NSString nsStringPath = new(path);
-                    ObjectiveC.Object nsUrl = new("NSURL");
-                    var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
-
-                    ObjectiveC.Object nsArray = new("NSArray");
-                    ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
-
-                    ObjectiveC.Object nsWorkspace = new("NSWorkspace");
-                    ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
-
-                    sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray);
-                }
-                else if (OperatingSystem.IsLinux())
-                {
-                    Process.Start("dbus-send", $"--session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:\"file://{path}\" string:\"\"");
-                }
-                else
-                {
-                    OpenFolder(Path.GetDirectoryName(path));
-                }
-            }
-            else
-            {
-                Logger.Notice.Print(LogClass.Application, $"File \"{path}\" doesn't exist!");
-            }
-        }
-
-        public static void OpenUrl(string url)
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                Process.Start(new ProcessStartInfo("cmd", $"/c start {url.Replace("&", "^&")}"));
-            }
-            else if (OperatingSystem.IsLinux())
-            {
-                Process.Start("xdg-open", url);
-            }
-            else if (OperatingSystem.IsMacOS())
-            {
-                ObjectiveC.NSString nsStringPath = new(url);
-                ObjectiveC.Object nsUrl = new("NSURL");
-                var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
-
-                ObjectiveC.Object nsWorkspace = new("NSWorkspace");
-                ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");
-
-                sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr);
-            }
-            else
-            {
-                Logger.Notice.Print(LogClass.Application, $"Cannot open url \"{url}\" on this platform!");
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/SetupValidator.cs b/src/Ryujinx.Ui.Common/Helper/SetupValidator.cs
deleted file mode 100644
index 65c38d7b..00000000
--- a/src/Ryujinx.Ui.Common/Helper/SetupValidator.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using Ryujinx.Common.Logging;
-using Ryujinx.HLE.FileSystem;
-using System;
-using System.IO;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    /// <summary>
-    /// Ensure installation validity
-    /// </summary>
-    public static class SetupValidator
-    {
-        public static bool IsFirmwareValid(ContentManager contentManager, out UserError error)
-        {
-            bool hasFirmware = contentManager.GetCurrentFirmwareVersion() != null;
-
-            if (hasFirmware)
-            {
-                error = UserError.Success;
-
-                return true;
-            }
-
-            error = UserError.NoFirmware;
-
-            return false;
-        }
-
-        public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion)
-        {
-            try
-            {
-                firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath);
-            }
-            catch (Exception)
-            {
-                firmwareVersion = null;
-            }
-
-            return error == UserError.NoFirmware && Path.GetExtension(baseApplicationPath).ToLowerInvariant() == ".xci" && firmwareVersion != null;
-        }
-
-        public static bool TryFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out UserError outError)
-        {
-            if (error == UserError.NoFirmware)
-            {
-                string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant();
-
-                // If the target app to start is a XCI, try to install firmware from it
-                if (baseApplicationExtension == ".xci")
-                {
-                    SystemVersion firmwareVersion;
-
-                    try
-                    {
-                        firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath);
-                    }
-                    catch (Exception)
-                    {
-                        firmwareVersion = null;
-                    }
-
-                    // The XCI is a valid firmware package, try to install the firmware from it!
-                    if (firmwareVersion != null)
-                    {
-                        try
-                        {
-                            Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
-
-                            contentManager.InstallFirmware(baseApplicationPath);
-
-                            Logger.Info?.Print(LogClass.Application, $"System version {firmwareVersion.VersionString} successfully installed.");
-
-                            outError = UserError.Success;
-
-                            return true;
-                        }
-                        catch (Exception) { }
-                    }
-
-                    outError = error;
-
-                    return false;
-                }
-            }
-
-            outError = error;
-
-            return false;
-        }
-
-        public static bool CanStartApplication(ContentManager contentManager, string baseApplicationPath, out UserError error)
-        {
-            if (Directory.Exists(baseApplicationPath) || File.Exists(baseApplicationPath))
-            {
-                string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant();
-
-                // NOTE: We don't force homebrew developers to install a system firmware.
-                if (baseApplicationExtension == ".nro" || baseApplicationExtension == ".nso")
-                {
-                    error = UserError.Success;
-
-                    return true;
-                }
-
-                return IsFirmwareValid(contentManager, out error);
-            }
-
-            error = UserError.ApplicationNotFound;
-
-            return false;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs b/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
deleted file mode 100644
index 3d27d3ff..00000000
--- a/src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using ShellLink;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static class ShortcutHelper
-    {
-        [SupportedOSPlatform("windows")]
-        private static void CreateShortcutWindows(string applicationFilePath, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
-        {
-            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
-            iconPath += ".ico";
-
-            MemoryStream iconDataStream = new(iconData);
-            var image = Image.Load(iconDataStream);
-            image.Mutate(x => x.Resize(128, 128));
-            SaveBitmapAsIcon(image, iconPath);
-
-            var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
-            shortcut.StringData.NameString = cleanedAppName;
-            shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
-        }
-
-        [SupportedOSPlatform("linux")]
-        private static void CreateShortcutLinux(string applicationFilePath, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
-        {
-            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
-            var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
-            iconPath += ".png";
-
-            var image = Image.Load<Rgba32>(iconData);
-            image.SaveAsPng(iconPath);
-
-            using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
-            outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath)}");
-        }
-
-        [SupportedOSPlatform("macos")]
-        private static void CreateShortcutMacos(string appFilePath, byte[] iconData, string desktopPath, string cleanedAppName)
-        {
-            string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
-            var plistFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.plist");
-            var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-launch-script.sh");
-            // Macos .App folder
-            string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents");
-            string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS");
-
-            if (!Directory.Exists(scriptFolderPath))
-            {
-                Directory.CreateDirectory(scriptFolderPath);
-            }
-
-            // Runner script
-            const string ScriptName = "runner.sh";
-            string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
-            using StreamWriter scriptFile = new(scriptPath);
-
-            scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath));
-
-            // Set execute permission
-            FileInfo fileInfo = new(scriptPath);
-            fileInfo.UnixFileMode |= UnixFileMode.UserExecute;
-
-            // img
-            string resourceFolderPath = Path.Combine(contentFolderPath, "Resources");
-            if (!Directory.Exists(resourceFolderPath))
-            {
-                Directory.CreateDirectory(resourceFolderPath);
-            }
-
-            const string IconName = "icon.png";
-            var image = Image.Load<Rgba32>(iconData);
-            image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
-
-            // plist file
-            using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
-            outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
-        }
-
-        public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
-        {
-            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
-            string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
-
-            if (OperatingSystem.IsWindows())
-            {
-                string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
-
-                CreateShortcutWindows(applicationFilePath, iconData, iconPath, cleanedAppName, desktopPath);
-
-                return;
-            }
-
-            if (OperatingSystem.IsLinux())
-            {
-                string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
-
-                Directory.CreateDirectory(iconPath);
-                CreateShortcutLinux(applicationFilePath, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
-
-                return;
-            }
-
-            if (OperatingSystem.IsMacOS())
-            {
-                CreateShortcutMacos(applicationFilePath, iconData, desktopPath, cleanedAppName);
-
-                return;
-            }
-
-            throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
-        }
-
-        private static string GetArgsString(string appFilePath)
-        {
-            // args are first defined as a list, for easier adjustments in the future
-            var argsList = new List<string>();
-
-            if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg))
-            {
-                argsList.Add("--root-data-dir");
-                argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
-            }
-
-            argsList.Add($"\"{appFilePath}\"");
-
-            return String.Join(" ", argsList);
-        }
-
-        /// <summary>
-        /// Creates a Icon (.ico) file using the source bitmap image at the specified file path.
-        /// </summary>
-        /// <param name="source">The source bitmap image that will be saved as an .ico file</param>
-        /// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
-        [SupportedOSPlatform("windows")]
-        private static void SaveBitmapAsIcon(Image source, string filePath)
-        {
-            // Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
-            byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
-            using FileStream fs = new(filePath, FileMode.Create);
-
-            fs.Write(header);
-            // Writing actual data
-            source.Save(fs, PngFormat.Instance);
-            // Getting data length (file length minus header)
-            long dataLength = fs.Length - header.Length;
-            // Write it in the correct place
-            fs.Seek(14, SeekOrigin.Begin);
-            fs.WriteByte((byte)dataLength);
-            fs.WriteByte((byte)(dataLength >> 8));
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/TitleHelper.cs b/src/Ryujinx.Ui.Common/Helper/TitleHelper.cs
deleted file mode 100644
index 089b5215..00000000
--- a/src/Ryujinx.Ui.Common/Helper/TitleHelper.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Ryujinx.HLE.Loaders.Processes;
-using System;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static class TitleHelper
-    {
-        public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, string pauseString = "")
-        {
-            if (activeProcess == null)
-            {
-                return String.Empty;
-            }
-
-            string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
-            string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
-            string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
-            string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
-
-            string appTitle = $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
-
-            if (!string.IsNullOrEmpty(pauseString))
-            {
-                appTitle += $" ({pauseString})";
-            }
-
-            return appTitle;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Helper/ValueFormatUtils.cs b/src/Ryujinx.Ui.Common/Helper/ValueFormatUtils.cs
deleted file mode 100644
index b1597a7c..00000000
--- a/src/Ryujinx.Ui.Common/Helper/ValueFormatUtils.cs
+++ /dev/null
@@ -1,219 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-
-namespace Ryujinx.Ui.Common.Helper
-{
-    public static class ValueFormatUtils
-    {
-        private static readonly string[] _fileSizeUnitStrings =
-        {
-            "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",  // Base 10 units, used for formatting and parsing
-            "KB", "MB", "GB", "TB", "PB", "EB",             // Base 2 units, used for parsing legacy values
-        };
-
-        /// <summary>
-        /// Used by <see cref="FormatFileSize"/>.
-        /// </summary>
-        public enum FileSizeUnits
-        {
-            Auto = -1,
-            Bytes = 0,
-            Kibibytes = 1,
-            Mebibytes = 2,
-            Gibibytes = 3,
-            Tebibytes = 4,
-            Pebibytes = 5,
-            Exbibytes = 6,
-            Kilobytes = 7,
-            Megabytes = 8,
-            Gigabytes = 9,
-            Terabytes = 10,
-            Petabytes = 11,
-            Exabytes = 12,
-        }
-
-        private const double SizeBase10 = 1000;
-        private const double SizeBase2 = 1024;
-        private const int UnitEBIndex = 6;
-
-        #region Value formatters
-
-        /// <summary>
-        /// Creates a human-readable string from a <see cref="TimeSpan"/>.
-        /// </summary>
-        /// <param name="timeSpan">The <see cref="TimeSpan"/> to be formatted.</param>
-        /// <returns>A formatted string that can be displayed in the UI.</returns>
-        public static string FormatTimeSpan(TimeSpan? timeSpan)
-        {
-            if (!timeSpan.HasValue || timeSpan.Value.TotalSeconds < 1)
-            {
-                // Game was never played
-                return TimeSpan.Zero.ToString("c", CultureInfo.InvariantCulture);
-            }
-
-            if (timeSpan.Value.TotalDays < 1)
-            {
-                // Game was played for less than a day
-                return timeSpan.Value.ToString("c", CultureInfo.InvariantCulture);
-            }
-
-            // Game was played for more than a day
-            TimeSpan onlyTime = timeSpan.Value.Subtract(TimeSpan.FromDays(timeSpan.Value.Days));
-            string onlyTimeString = onlyTime.ToString("c", CultureInfo.InvariantCulture);
-
-            return $"{timeSpan.Value.Days}d, {onlyTimeString}";
-        }
-
-        /// <summary>
-        /// Creates a human-readable string from a <see cref="DateTime"/>.
-        /// </summary>
-        /// <param name="utcDateTime">The <see cref="DateTime"/> to be formatted. This is expected to be UTC-based.</param>
-        /// <param name="culture">The <see cref="CultureInfo"/> that's used in formatting. Defaults to <see cref="CultureInfo.CurrentCulture"/>.</param>
-        /// <returns>A formatted string that can be displayed in the UI.</returns>
-        public static string FormatDateTime(DateTime? utcDateTime, CultureInfo culture = null)
-        {
-            culture ??= CultureInfo.CurrentCulture;
-
-            if (!utcDateTime.HasValue)
-            {
-                // In the Avalonia UI, this is turned into a localized version of "Never" by LocalizedNeverConverter.
-                return "Never";
-            }
-
-            return utcDateTime.Value.ToLocalTime().ToString(culture);
-        }
-
-        /// <summary>
-        /// Creates a human-readable file size string.
-        /// </summary>
-        /// <param name="size">The file size in bytes.</param>
-        /// <param name="forceUnit">Formats the passed size value as this unit, bypassing the automatic unit choice.</param>
-        /// <returns>A human-readable file size string.</returns>
-        public static string FormatFileSize(long size, FileSizeUnits forceUnit = FileSizeUnits.Auto)
-        {
-            if (size <= 0)
-            {
-                return $"0 {_fileSizeUnitStrings[0]}";
-            }
-
-            int unitIndex = (int)forceUnit;
-            if (forceUnit == FileSizeUnits.Auto)
-            {
-                unitIndex = Convert.ToInt32(Math.Floor(Math.Log(size, SizeBase10)));
-
-                // Apply an upper bound so that exabytes are the biggest unit used when formatting.
-                if (unitIndex > UnitEBIndex)
-                {
-                    unitIndex = UnitEBIndex;
-                }
-            }
-
-            double sizeRounded;
-
-            if (unitIndex > UnitEBIndex)
-            {
-                sizeRounded = Math.Round(size / Math.Pow(SizeBase10, unitIndex - UnitEBIndex), 1);
-            }
-            else
-            {
-                sizeRounded = Math.Round(size / Math.Pow(SizeBase2, unitIndex), 1);
-            }
-
-            string sizeFormatted = sizeRounded.ToString(CultureInfo.InvariantCulture);
-
-            return $"{sizeFormatted} {_fileSizeUnitStrings[unitIndex]}";
-        }
-
-        #endregion
-
-        #region Value parsers
-
-        /// <summary>
-        /// Parses a string generated by <see cref="FormatTimeSpan"/> and returns the original <see cref="TimeSpan"/>.
-        /// </summary>
-        /// <param name="timeSpanString">A string representing a <see cref="TimeSpan"/>.</param>
-        /// <returns>A <see cref="TimeSpan"/> object. If the input string couldn't been parsed, <see cref="TimeSpan.Zero"/> is returned.</returns>
-        public static TimeSpan ParseTimeSpan(string timeSpanString)
-        {
-            TimeSpan returnTimeSpan = TimeSpan.Zero;
-
-            // An input string can either look like "01:23:45" or "1d, 01:23:45" if the timespan represents a duration of more than a day.
-            // Here, we split the input string to check if it's the former or the latter.
-            var valueSplit = timeSpanString.Split(", ");
-            if (valueSplit.Length > 1)
-            {
-                var dayPart = valueSplit[0].Split("d")[0];
-                if (int.TryParse(dayPart, out int days))
-                {
-                    returnTimeSpan = returnTimeSpan.Add(TimeSpan.FromDays(days));
-                }
-            }
-
-            if (TimeSpan.TryParse(valueSplit.Last(), out TimeSpan parsedTimeSpan))
-            {
-                returnTimeSpan = returnTimeSpan.Add(parsedTimeSpan);
-            }
-
-            return returnTimeSpan;
-        }
-
-        /// <summary>
-        /// Parses a string generated by <see cref="FormatDateTime"/> and returns the original <see cref="DateTime"/>.
-        /// </summary>
-        /// <param name="dateTimeString">The string representing a <see cref="DateTime"/>.</param>
-        /// <returns>A <see cref="DateTime"/> object. If the input string couldn't be parsed, <see cref="DateTime.UnixEpoch"/> is returned.</returns>
-        public static DateTime ParseDateTime(string dateTimeString)
-        {
-            if (!DateTime.TryParse(dateTimeString, CultureInfo.CurrentCulture, out DateTime parsedDateTime))
-            {
-                // Games that were never played are supposed to appear before the oldest played games in the list,
-                // so returning DateTime.UnixEpoch here makes sense.
-                return DateTime.UnixEpoch;
-            }
-
-            return parsedDateTime;
-        }
-
-        /// <summary>
-        /// Parses a string generated by <see cref="FormatFileSize"/> and returns a <see cref="long"/> representing a number of bytes.
-        /// </summary>
-        /// <param name="sizeString">A string representing a file size formatted with <see cref="FormatFileSize"/>.</param>
-        /// <returns>A <see cref="long"/> representing a number of bytes.</returns>
-        public static long ParseFileSize(string sizeString)
-        {
-            // Enumerating over the units backwards because otherwise, sizeString.EndsWith("B") would exit the loop in the first iteration.
-            for (int i = _fileSizeUnitStrings.Length - 1; i >= 0; i--)
-            {
-                string unit = _fileSizeUnitStrings[i];
-                if (!sizeString.EndsWith(unit))
-                {
-                    continue;
-                }
-
-                string numberString = sizeString.Split(" ")[0];
-                if (!double.TryParse(numberString, CultureInfo.InvariantCulture, out double number))
-                {
-                    break;
-                }
-
-                double sizeBase = SizeBase2;
-
-                // If the unit index is one that points to a base 10 unit in the FileSizeUnitStrings array, subtract 6 to arrive at a usable power value.
-                if (i > UnitEBIndex)
-                {
-                    i -= UnitEBIndex;
-                    sizeBase = SizeBase10;
-                }
-
-                number *= Math.Pow(sizeBase, i);
-
-                return Convert.ToInt64(number);
-            }
-
-            return 0;
-        }
-
-        #endregion
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApi.cs b/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApi.cs
deleted file mode 100644
index ff0b80c4..00000000
--- a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApi.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Amiibo
-{
-    public struct AmiiboApi : IEquatable<AmiiboApi>
-    {
-        [JsonPropertyName("name")]
-        public string Name { get; set; }
-        [JsonPropertyName("head")]
-        public string Head { get; set; }
-        [JsonPropertyName("tail")]
-        public string Tail { get; set; }
-        [JsonPropertyName("image")]
-        public string Image { get; set; }
-        [JsonPropertyName("amiiboSeries")]
-        public string AmiiboSeries { get; set; }
-        [JsonPropertyName("character")]
-        public string Character { get; set; }
-        [JsonPropertyName("gameSeries")]
-        public string GameSeries { get; set; }
-        [JsonPropertyName("type")]
-        public string Type { get; set; }
-
-        [JsonPropertyName("release")]
-        public Dictionary<string, string> Release { get; set; }
-
-        [JsonPropertyName("gamesSwitch")]
-        public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
-
-        public readonly override string ToString()
-        {
-            return Name;
-        }
-
-        public readonly string GetId()
-        {
-            return Head + Tail;
-        }
-
-        public readonly bool Equals(AmiiboApi other)
-        {
-            return Head + Tail == other.Head + other.Tail;
-        }
-
-        public readonly override bool Equals(object obj)
-        {
-            return obj is AmiiboApi other && Equals(other);
-        }
-
-        public readonly override int GetHashCode()
-        {
-            return HashCode.Combine(Head, Tail);
-        }
-
-        public static bool operator ==(AmiiboApi left, AmiiboApi right)
-        {
-            return left.Equals(right);
-        }
-
-        public static bool operator !=(AmiiboApi left, AmiiboApi right)
-        {
-            return !(left == right);
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs b/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
deleted file mode 100644
index 3c62b7cc..00000000
--- a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Amiibo
-{
-    public class AmiiboApiGamesSwitch
-    {
-        [JsonPropertyName("amiiboUsage")]
-        public List<AmiiboApiUsage> AmiiboUsage { get; set; }
-        [JsonPropertyName("gameID")]
-        public List<string> GameId { get; set; }
-        [JsonPropertyName("gameName")]
-        public string GameName { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiUsage.cs b/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiUsage.cs
deleted file mode 100644
index 3c774fd5..00000000
--- a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboApiUsage.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Amiibo
-{
-    public class AmiiboApiUsage
-    {
-        [JsonPropertyName("Usage")]
-        public string Usage { get; set; }
-        [JsonPropertyName("write")]
-        public bool Write { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJson.cs b/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJson.cs
deleted file mode 100644
index c9d91c50..00000000
--- a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJson.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Amiibo
-{
-    public struct AmiiboJson
-    {
-        [JsonPropertyName("amiibo")]
-        public List<AmiiboApi> Amiibo { get; set; }
-        [JsonPropertyName("lastUpdated")]
-        public DateTime LastUpdated { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs b/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
deleted file mode 100644
index 4906c652..00000000
--- a/src/Ryujinx.Ui.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Amiibo
-{
-    [JsonSerializable(typeof(AmiiboJson))]
-    public partial class AmiiboJsonSerializerContext : JsonSerializerContext
-    {
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Github/GithubReleaseAssetJsonResponse.cs b/src/Ryujinx.Ui.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
deleted file mode 100644
index 67d238d2..00000000
--- a/src/Ryujinx.Ui.Common/Models/Github/GithubReleaseAssetJsonResponse.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Ryujinx.Ui.Common.Models.Github
-{
-    public class GithubReleaseAssetJsonResponse
-    {
-        public string Name { get; set; }
-        public string State { get; set; }
-        public string BrowserDownloadUrl { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonResponse.cs b/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonResponse.cs
deleted file mode 100644
index 0f83e32c..00000000
--- a/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonResponse.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections.Generic;
-
-namespace Ryujinx.Ui.Common.Models.Github
-{
-    public class GithubReleasesJsonResponse
-    {
-        public string Name { get; set; }
-        public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonSerializerContext.cs b/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
deleted file mode 100644
index 8a19277b..00000000
--- a/src/Ryujinx.Ui.Common/Models/Github/GithubReleasesJsonSerializerContext.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ui.Common.Models.Github
-{
-    [JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
-    public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext
-    {
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg b/src/Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg
deleted file mode 100644
index 03585e65..00000000
--- a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st1{fill:#02c5e5}</style><style id="style2-6" type="text/css">.st1{fill:#02c5e5}.st3{fill:#fff}</style><g id="g344" transform="translate(0,300)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="225.8 469.9 250 469.9 237.9 448.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="237.9 626.9 225.8 605.9 250 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="148.9 537.9 169.9 550 169.9 525.8" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="305.9 550 305.9 525.8 326.9 537.9" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="m 388.84323,464.93186 0.0252,-5.22079 0.35628,-387.023108 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/></g><ellipse id="path4030" cx="-630.031" cy="861.013" rx="15.407" ry="14.105" transform="scale(-1,1)" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4038" d="m 531.57205,538.85036 v 45.92786" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4040" d="M 538.66113,544.78398 V 581.251" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4062" d="m 618.21618,561.30922 c 0.15897,-2.39247 0.93393,-4.19426 2.34943,-5.4612 1.05382,-0.94329 2.4969,-1.60711 4.18689,-1.92587 0.38638,-0.0728 1.08711,-0.17756 1.09745,-0.16356 0,0.005 0.0932,0.85525 0.2017,1.89259 0.10822,1.03731 0.20533,1.93952 0.21568,2.00495 0.0181,0.10453 0.0103,0.11877 -0.0516,0.11877 -0.12143,0 -0.66218,0.12325 -1.06042,0.24145 -1.89486,0.56317 -2.9076,1.70318 -3.13568,3.52943 -0.0526,0.41968 0.2402,1.20332 0.3147,1.59414 0.19574,1.0321 0.5477,1.44923 1.24585,1.96064 0.54534,0.39941 0.84078,0.63241 1.52991,0.63397 0.49114,0 0.79513,-0.17703 1.12084,-0.34918 0.22397,-0.11875 0.54525,-0.72408 0.72476,-0.97125 0.4284,-0.59002 0.57331,-0.18167 1.33421,-2.91459 0.47521,-1.70735 0.75977,-2.52129 1.19088,-3.4071 0.58401,-1.19961 1.35632,-2.06979 2.41398,-2.71969 0.58281,-0.35813 1.33375,-0.64229 2.04739,-0.77469 0.33923,-0.0633 0.49023,-0.0718 1.18512,-0.0711 0.6888,7.5e-4 0.84197,0.01 1.1342,0.0705 1.71036,0.34984 3.14515,1.32777 3.98586,2.71644 0.37788,0.62406 0.6928,1.43192 0.8702,2.23216 0.38944,1.75661 0.31125,4.08353 -0.19239,5.72547 -0.23225,0.75754 -0.63066,1.547 -1.06364,2.10803 -0.29761,0.38576 -1.03764,1.06284 -1.46261,1.33836 -0.68025,0.44086 -1.27214,1.08216 -2.11357,1.24388 -0.42538,0.0817 -1.27033,-0.14168 -1.5376,-0.14168 h -0.15716 l -2.2e-4,-0.18229 c -1.6e-4,-0.10006 -0.0391,-0.97392 -0.0865,-1.94151 -0.0477,-0.9676 -0.0862,-1.8095 -0.0862,-1.87098 l -7e-5,-0.11166 0.30292,-0.0566 c 0.67911,-0.12659 0.64274,-0.69151 1.05495,-1.00838 0.80274,-0.61701 1.57932,-1.59904 1.57884,-3.10599 -2.4e-4,-0.99245 -0.26656,-1.2378 -0.6209,-1.90047 -0.41109,-0.7689 -0.52472,-0.63395 -1.25089,-0.66875 -0.54033,-0.0264 -0.60261,0.54818 -0.97987,0.86389 -0.60357,0.50503 -0.65515,0.26871 -1.33681,2.74768 -0.53065,1.92992 -1.61672,3.72692 -2.02402,4.67676 -0.7236,1.68735 -1.46229,1.88688 -2.90464,2.54118 -0.86271,0.39132 -1.65737,0.56338 -2.80448,0.60727 -1.3619,0.0524 -2.61283,-0.24592 -3.80829,-0.90695 -1.3364,-0.73899 -2.29253,-1.88343 -2.83806,-3.39691 -0.47562,-1.31947 -0.68418,-3.07542 -0.56986,-4.79727 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4064" d="m 630.09646,971.66625 h 11.20079 l -7.7e-4,4.47736 c -3.9e-4,2.46263 -0.0181,4.8542 -0.0344,5.31477 -0.12014,3.00951 -0.56807,4.32259 -1.86223,5.4598 -1.43936,1.26481 -3.65136,1.78958 -5.84831,1.38753 -1.22398,-0.224 -2.30114,-0.78622 -3.1233,-1.63027 -0.75525,-0.77541 -1.34589,-2.02193 -1.58341,-3.3415 -0.0526,-0.2928 -0.0649,-0.32336 -0.10591,-0.26949 -0.0258,0.0337 -0.20067,0.27472 -0.38963,0.53623 -0.79262,1.09807 -1.46856,1.72397 -2.8174,2.60895 -0.78277,0.51353 -1.17221,0.74339 -4.12365,2.43453 l -2.49548,1.4299 -0.008,-2.44288 c -0.005,-1.92858 2.7e-4,-2.45065 0.0344,-2.47945 0.0234,-0.0215 1.34449,-0.8352 2.93457,-1.81113 4.5931,-2.81923 5.11319,-3.17081 5.65776,-3.8248 0.54019,-0.64863 0.67406,-1.16979 0.70337,-2.7382 l 0.0181,-0.99053 h -4.67857 -4.67867 v -2.06046 -2.06036 h 11.20079 z m 1.74946,9.28763 c 0.0409,0.67298 0.11392,1.26781 0.18719,1.52499 0.22165,0.77651 0.88153,1.38438 1.75173,1.61386 0.32467,0.0855 1.148,0.12136 1.50829,0.0653 0.87376,-0.13534 1.48211,-0.5375 1.85019,-1.22332 0.35302,-0.65774 0.37769,-0.95998 0.37905,-4.65174 l 7.5e-4,-2.49624 h -2.85643 -2.85653 l 7e-5,2.29025 c 0,1.25954 0.0181,2.55403 0.0356,2.87661 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4066" d="m 618.48834,960.72379 c 0.26992,-3.13481 1.47063,-5.14907 3.82731,-6.42085 0.94544,-0.51008 2.47246,-0.96116 3.66673,-1.08314 l 0.21439,-0.0214 0.0207,0.10785 c 0.0372,0.19794 0.41957,3.90855 0.40445,3.92234 -0.008,0.007 -0.17193,0.0441 -0.3639,0.0822 -0.19212,0.0376 -0.53821,0.12634 -0.76937,0.19651 -1.79072,0.54475 -2.7801,1.57117 -3.10355,3.21988 -0.0989,0.50413 -0.10744,1.60822 -0.0155,2.14051 0.12169,0.71048 0.32194,1.25035 0.6218,1.6747 0.41144,0.58234 0.98794,1.0195 1.60624,1.21829 0.34978,0.11236 1.05168,0.14484 1.3996,0.0645 0.68302,-0.15762 1.12961,-0.53488 1.53764,-1.29896 0.28622,-0.53585 0.48608,-1.14697 1.12493,-3.44026 0.58179,-2.0886 0.89522,-2.93441 1.4688,-3.96444 0.54763,-0.9834 1.29532,-1.75609 2.25091,-2.32632 1.0162,-0.60643 2.16997,-0.88864 3.44103,-0.84174 1.09522,0.0405 2.1108,0.34696 3.03462,0.9161 0.67952,0.41875 1.15791,0.85897 1.62314,1.49397 0.94821,1.29426 1.41875,3.00624 1.41828,5.1604 -5.4e-4,2.4013 -0.5283,4.2219 -1.61346,5.56569 -0.28052,0.34751 -0.87705,0.89358 -1.25657,1.15047 -1.02517,0.69385 -2.17752,1.07827 -3.55571,1.18615 -0.21154,0.0168 -0.38907,0.0262 -0.39448,0.0215 -0.0155,-0.0141 -0.21309,-4.13646 -0.20041,-4.14922 0.008,-0.007 0.14966,-0.0386 0.32003,-0.0726 0.96084,-0.19177 1.73387,-0.57719 2.16612,-1.08024 0.33457,-0.38922 0.56064,-0.89429 0.68786,-1.53658 0.1015,-0.51332 0.11134,-1.67163 0.0181,-2.21419 -0.14526,-0.84985 -0.46593,-1.54361 -0.92193,-1.99457 -0.48336,-0.47793 -1.31478,-0.61609 -1.9837,-0.32951 -0.30417,0.13037 -0.66295,0.44566 -0.87729,0.7711 -0.39693,0.60258 -0.7762,1.64298 -1.28809,3.53321 -0.61793,2.28163 -1.08691,3.57856 -1.64611,4.55253 -0.90497,1.57616 -2.40653,2.63296 -4.21401,2.96573 -0.65494,0.12066 -1.14141,0.15526 -1.88939,0.13511 -0.52546,-0.0141 -0.75937,-0.0355 -1.08943,-0.0994 -1.82284,-0.35238 -3.39382,-1.33729 -4.32844,-2.71383 -0.65796,-0.969 -1.07881,-2.20396 -1.27779,-3.74995 -0.0534,-0.41339 -0.0974,-2.3393 -0.0626,-2.74128 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4068" d="m 630.08177,575.12806 11.69573,-0.0768 0.11296,2.83872 -0.11296,2.7832 -10.22217,-0.0657 -8.46941,0.0657 -0.23931,4.64789 -0.21033,5.23455 -2.19525,-0.11373 h -1.89113 v -7.29401 l -0.13688,-8.09662 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path249" d="m 564.81854,320.07351 2.80254,-2.94783 2.10843,-1.80063 3.89781,-2.62722 4.93974,-2.563 3.81131,-1.26428 3.8729,-0.82566 1.38974,-0.20307 2.88842,-0.16699 h 57.79227 l 1.57144,0.1495 1.7697,0.23946 1.77484,0.23845 2.72964,0.54365 2.31281,0.60657 2.44326,0.75609 2.94394,0.94407 2.12886,0.90455 3.8498,1.71936 2.75741,1.53909 2.10581,1.19691 3.23498,2.16487 2.4201,1.63817 1.43595,1.20589 1.89607,1.45278 3.21175,2.60881 2.42278,2.54722 4.25902,4.70095 2.59949,3.25688 1.67743,2.63026 1.27103,2.18885 1.91183,3.73696 0.72706,1.65104 1.16131,2.96921 0.66224,2.6045 0.78479,3.27949 0.33987,2.68699 0.0483,2.38913 v 4.00596 2.85158 877.28853 l -0.16384,2.4984 -0.34524,3.4016 -1.29885,4.7808 -1.23966,3.7841 -3.60497,7.2728 -2.57375,4.0663 -2.46855,3.2069 -1.48186,1.9802 -2.66944,2.87 -3.06989,3.0298 -2.17649,1.9303 -4.01872,3.1261 -4.11447,2.8611 -2.30753,1.2764 -3.52352,1.8502 -3.6903,1.6841 -4.15406,1.4576 -3.72593,1.1705 -3.68244,0.746 -3.28501,0.4427 -3.07889,0.2681 h -56.72802 l -2.27377,-0.2166 -3.66214,-0.647 -2.13716,-0.5101 -2.60358,-0.9022 -3.70761,-1.5158 -3.72085,-1.8958 -3.11883,-1.9649 -2.49439,-2.0644 -3.08564,-2.8864 -3.11412,-3.839 -2.38795,-3.9255 -1.37928,-3.2422 -1.06978,-2.9089 -0.81446,-3.3604 -0.4154,-3.6114 -0.024,-2.148 V 343.23256 l 0.28062,-2.94096 0.63887,-3.85473 1.31769,-4.26752 1.53215,-3.69272 2.5337,-4.4686 1.96993,-2.5833 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path253" d="m 694.62149,334.10362 2.87464,2.17056 1.39448,1.27449 1.10633,1.19174 1.33926,1.50114 1.38209,1.74045 1.13752,1.55135 1.14707,1.6191 1.76331,2.78539 1.13353,1.9937 0.91903,1.69462 1.33241,2.59815 1.11209,2.33 1.56583,3.39111 0.63568,1.22029 0.77282,1.85718 0.72486,1.75471 0.98903,2.11635 1.04466,2.26736 0.86003,1.7056 0.74871,1.46183 0.77843,1.50459 1.16158,2.03635 0.69941,1.16948 1.32156,2.11591 1.16136,1.5888 0.91829,1.1277 1.46722,1.69949 1.41993,1.42143 1.99344,1.72936 2.2557,1.72741 2.15114,1.20765 1.3718,0.68691 3.115,1.23393 4.1538,1.06385 3.08686,0.4687 3.22131,0.30291 h 28.48289 l 0.94647,0.0524 0.97841,0.35799 1.16352,0.47513 0.9822,0.70154 1.01456,1.07822 0.92826,1.35838 0.65022,1.72693 0.1277,1.59566 -0.29606,1.44502 -0.74147,1.59474 -1.99052,3.45657 -2.4225,4.16279 -2.33536,3.53915 -1.37414,1.9664 -1.24262,1.70801 -1.41326,1.83088 -1.34109,1.74508 -2.14664,2.66591 -1.97231,2.31029 -1.08591,1.37517 -2.41419,2.77055 -1.30886,1.52879 -3.03361,3.40228 -1.58159,1.80779 -1.34438,1.31431 -2.46317,2.6295 -1.04614,1.0908 -4.84623,5.03258 -3.60112,3.77568 -1.74314,1.82893 -2.10543,2.2459 -6.06161,6.49298 -2.39368,2.59389 -2.01406,2.20329 -1.6282,1.85603 -1.14047,1.25547 -1.6465,1.98517 -1.72596,2.18615 -1.52881,1.91959 -1.25534,1.48184 -1.12938,1.52402 -1.65189,2.2517 -1.15137,1.60225 -1.31306,1.81213 -1.08907,1.73832 -1.86192,2.96443 -1.97162,3.32339 -1.21492,2.47246 -1.36959,2.68936 -0.95325,2.42774 -1.07073,2.91455 -0.76263,2.02052 h -0.62464"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path255" d="m 554.98557,806.60461 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97257 -0.93192,0.98281 -0.8244,1.30431 -0.46075,1.2916 -0.0637,0.91287 -0.15809,2.36292 -0.25772,3.06459 -0.2171,3.23629 -0.2039,3.99231 -0.12562,3.06084 -0.14526,4.35384 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37395 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.13471 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path298" d="m 554.91046,880.77518 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path300" d="m 555.35214,1000.9073 -0.70664,0.01 -1.15041,0.3129 -0.94439,0.9042 -0.33283,0.8403 v 55.3836 l 0.35102,0.988 1.16661,1.0639 0.76614,0.2105 0.79763,-0.043 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path302" d="m 683.4822,322.5276 1.80756,-0.36865 3.52048,0.79736 3.29989,0.79341 3.35684,0.85712 10.58481,3.05757 8.24268,2.61795 6.98289,2.30801 8.19137,2.72032 6.85494,2.1232 7.56186,2.22326 3.02344,0.89258 3.01485,0.78292 2.59184,0.6545 4.39682,1.01106 3.44978,0.73216 4.14889,0.73189 5.67397,0.74901 2.26019,0.25821 2.51619,0.19404 1.51308,0.53857 1.71443,0.82574 1.15366,0.80631 0.81926,0.61787 1.09348,1.17223 1.28918,1.66295 1.03628,2.03633 0.40058,1.60306 0.18894,1.03784 v 22.44381 l -0.19091,1.309 -0.49575,1.41249 -0.82966,1.654 -0.83314,1.22068 -1.26559,1.52171 -1.47306,1.67951 -1.74719,1.81065 -1.52584,1.67117 -1.0269,1.42993 -0.51569,0.92494"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path304" d="m 555.11995,518.09615 -1.01033,0.39258 -1.22841,0.93655 -1.2742,1.02924 -1.33354,1.35102 -1.34981,1.59351 -1.40742,1.80058 -1.06793,1.49244 -0.85098,1.20282 -0.89272,1.39504 -0.99731,1.62995 -0.60208,1.24653 -0.8025,1.69239 -0.93246,1.96822 -0.91473,2.23059 -0.62621,1.91229 -0.57345,2.01006 -0.59474,2.80402 -0.14894,0.35985 -1.18136,-0.13793 -0.97443,-0.18501 -1.29147,-0.54083 -1.00174,-0.69084 -1.15445,-0.99791 -0.60398,-0.85223 -0.49335,-1.12318 -0.37025,-1.37685 v -45.45096 l -0.20339,-1.17956 -0.74794,-1.09777 -0.87864,-0.84867 -1.1084,-0.66091 -1.62768,-0.61457 -1.99954,-0.31262 -2.41898,-0.0433 -3.34195,0.51108 -2.789,1.02869 -1.75751,0.92812 -1.48061,0.99716 -2.10544,1.93079 -1.35698,1.79438 -0.77464,1.80822 -0.53822,2.14889 -0.17548,1.82929 v 15.40503 l -0.74254,2.33437 -0.81509,3.04978 -0.66374,2.10772 -1.44608,5.41074 -0.10817,0.54556 -0.36239,1.62223 -0.43835,2.01252 -0.52816,2.59666 -0.51106,2.94424 -0.53199,3.41725 -0.52183,3.69125 -0.27377,2.56523 -0.17416,1.97814 -0.12505,1.76866 -0.16865,2.53094 -0.0926,2.51807 -0.10085,2.96479 -0.0322,3.59841 0.1372,3.62771 0.15883,3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path306" d="m 555.11995,607.38224 -1.01033,-0.39258 -1.22841,-0.93654 -1.2742,-1.02925 -1.33354,-1.35102 -1.34981,-1.5935 -1.40742,-1.80059 -1.06793,-1.49243 -0.85098,-1.20282 -0.89272,-1.39505 -0.99731,-1.62995 -0.60208,-1.24653 -0.8025,-1.69239 -0.93246,-1.96821 -0.91473,-2.23059 -0.62621,-1.9123 -0.57345,-2.01006 -0.59474,-2.80402 -0.14894,-0.35985 -1.18136,0.13793 -0.97443,0.18501 -1.29147,0.54083 -1.00174,0.69084 -1.15445,0.99792 -0.60398,0.85223 -0.49335,1.12317 -0.37025,1.37685 v 45.45097 l -0.20339,1.17956 -0.74794,1.09777 -0.87864,0.84866 -1.1084,0.66092 -1.62768,0.61456 -1.99954,0.31262 -2.41898,0.0433 -3.34195,-0.51107 -2.789,-1.0287 -1.75751,-0.92812 -1.48061,-0.99715 -2.10544,-1.93079 -1.35698,-1.79438 -0.77464,-1.80823 -0.53822,-2.14889 -0.17548,-1.82929 v -15.40503 l -0.74254,-2.33437 -0.81509,-3.04977 -0.66374,-2.10773 -1.44608,-5.41074 -0.10817,-0.54555 -0.36239,-1.62224 -0.43835,-2.01252 -0.52816,-2.59665 -0.51106,-2.94425 -0.53199,-3.41725 -0.52183,-3.69125 -0.27377,-2.56522 -0.17416,-1.97815 -0.12505,-1.76866 -0.16865,-2.53094 -0.0926,-2.51807 -0.10085,-2.96479 -0.0322,-3.5984 0.1372,-3.62772 0.15883,-3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path310" d="m 629.00102,930.67137 h 6.14653 l 2.04067,0.16215 1.12524,0.1958 1.57485,0.44983 1.37911,0.54025 1.49645,0.7516 1.16369,0.77595 1.20645,0.95903 1.07493,1.06679 1.10141,1.41857 0.59407,1.15018 0.53577,1.29561 0.50772,1.37166 0.10921,1.53404 0.0194,1.06304 v 58.84883 l -0.13659,1.1193 -0.20644,0.9935 -0.32745,0.917 -0.29571,0.8905 -0.50231,0.9886 -0.70348,1.073 -0.72708,0.8329 -1.14245,1.2323 -0.95483,0.8506 -1.12308,0.74 -1.3029,0.7638 -1.57811,0.6202 -1.75304,0.421 -1.62477,0.2527 -1.92906,0.036 h -12.21387 l -1.24442,-0.1438 -1.4416,-0.2655 -1.20902,-0.3547 -1.34067,-0.5911 -1.25475,-0.6462 -0.90721,-0.5402 -1.03832,-0.822 -0.71078,-0.7398 -0.67126,-0.637 -1.26722,-1.7893 -1.08212,-2.3971 -0.42262,-1.7353 -0.0315,-1.7747 v -59.09121 l 0.14146,-0.91134 0.21007,-0.66319 0.29836,-1.07418 0.44186,-1.07962 0.47325,-1.02037 0.3698,-0.61649 0.99623,-1.3542 0.95716,-1.00285 0.94225,-0.85279 0.88252,-0.60543 1.18795,-0.67902 1.33894,-0.6658 0.87252,-0.36273 0.97938,-0.32262 0.90474,-0.18457 1.43288,-0.23808 0.46681,-0.0584 1.01236,-0.055 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path320" d="m 705.29946,404.37113 h 4.94953 l 1.01129,0.19824 1.02198,0.65847 0.7694,0.84434 0.62305,1.2788 0.41165,1.37503 0.60375,2.17711 0.53032,2.14857 0.38266,1.97177 0.31418,1.95565 0.25283,2.01634 0.22113,2.18648 0.14186,2.361 0.0464,2.06343 -0.0339,2.90094 -0.18666,2.93049 -0.2597,3.12611 -0.3257,2.7483 -0.47254,2.43606 -0.38375,2.06954 -0.62275,2.43127 -0.48757,1.70574 -0.56732,1.13614 -0.65604,0.75733 -0.78933,0.54765 -0.77997,0.31884 -0.82705,0.0912 h -5.1673 -0.22961 V 404.3608 Z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path322" d="m 555.36415,396.79743 h -3.36229 l -0.95244,0.2579 -0.88685,0.75198 -0.3797,1.096 v 10.8053 l 0.39974,1.00083 0.47383,0.71418 0.63631,0.44263 0.50741,0.16001 h 3.36617 0.21167 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path324" d="m 606.45914,1054.8828 h 46.6816 l -23.3408,37.0116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path326" d="m 606.45914,1099.1543 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path328" d="m 606.45914,1143.4531 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path330" d="m 631.08566,1044.0909 h 27.01297 l 1.86984,0.2805 1.34197,0.3596 1.60607,0.6644 1.16604,0.7523 1.14122,0.8781 0.78333,0.8256 0.70342,0.7968 0.63184,1.1132 0.47977,0.9893 0.34526,1.0282 0.24865,1.1979 0.0693,0.8321 v 125.4568 l -0.0521,0.8725 -0.16665,1.0509 -0.4222,1.198 -0.73285,1.4957 -0.85365,1.1513 -1.41766,1.3555 -1.17786,0.9192 -1.59645,0.8597 -1.9127,0.616 -1.74431,0.1955 h -57.29204 l -1.482,-0.1172 -1.53793,-0.38 -1.02579,-0.42 -1.04703,-0.5563 -0.79838,-0.4864 -1.0868,-0.8174 -1.17978,-1.2797 -0.68706,-0.9209 -0.43671,-0.7767 -0.39717,-0.767 -0.36431,-1.0377 -0.17137,-0.7968 -0.0855,-1.2218 v -125.4649 l 0.0755,-1.1013 0.20402,-0.9527 0.22661,-0.7999 0.34294,-0.7651 0.79684,-1.4733 0.86432,-1.1445 1.36362,-1.2251 1.4025,-0.9497 0.76822,-0.4027 1.66903,-0.5936 1.31204,-0.2503 1.48443,-0.1826 1.15796,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path332" d="m 584.21811,307.65169 v -3.15652 l 0.37148,-1.45881 0.75589,-1.0701 1.18763,-0.98136 1.7025,-0.4849 h 45.22792 l 1.58355,0.18907 1.21322,0.58954 0.86017,0.63523 0.62083,0.6164 0.7767,1.22224 0.27256,1.40251 v 2.49159 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path334" d="m 554.98557,732.43405 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.1854 0.30831,1.25066 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path460" d="m 575.40725,1292.5752 c -8.50513,-4.4396 -14.59302,-11.4224 -17.41944,-18.9224 -0.26068,-0.6918 -2.10217,-5.5985 -2.32407,-16.4555 -0.95755,-46.8522 0.0692,-191.628 0.0924,-454.79146 0.0395,-447.17165 -1.16464,-463.77985 2.13444,-471.06146 4.14474,-9.14813 14.82174,-19.11565 24.20501,-21.93419 4.35355,-1.30772 20.60861,-0.88744 41.2504,-0.85913 9.13704,0.0125 16.72265,-0.38909 22.30143,-0.24437 9.7504,0.25294 14.61876,1.40481 19.8754,3.83273 13.20934,6.10107 27.37811,16.4207 32.31917,28.24068 1.2204,2.91943 4.50669,7.46836 6.1373,11.04497 l 1.41675,449.7216 -1.5273,449.96593 -4.08634,10.2294 c -5.14691,12.8843 -20.61785,27.6214 -33.70017,32.5287 -8.98936,3.372 -15.168,3.8603 -44.99389,3.8243 -13.98709,-0.017 -20.27955,0.078 -25.76681,0.1196 -1.4993,0.012 -2.53237,0.1219 -3.63781,0.1486 -1.8856,0.045 -3.47223,-0.1698 -5.13087,-0.6073 -1.2319,-0.3249 -1.88857,-0.4449 -3.07941,-0.9415 -0.66852,-0.2788 -1.67524,-0.6042 -2.54621,-0.9578 z m 96.94271,-95.8531 c 0.34361,-0.068 1.16774,-0.4225 1.45971,-0.6578 1.57938,-1.2724 3.13254,-2.332 3.76998,-3.2892 0.7553,-1.134 1.14301,-187.0038 1.15874,-414.46917 l -0.57612,-411.57378 -4.84312,-3.50599 c -3.43566,-2.48711 -8.52491,-1.47394 -44.87908,-1.47394 -41.01713,0 -42.12736,-0.69464 -45.65154,2.83862 -1.56374,1.56777 -1.68966,2.84556 -1.76015,34.2526 -0.0453,20.16919 -0.25443,52.7638 -0.18971,105.84008 0.042,34.48838 -0.39971,77.46436 -0.36851,131.48656 0.0237,40.99241 -0.34276,87.99166 -0.34276,142.48967 0,287.55485 0.28324,410.83535 1.67493,413.44235 1.09524,2.0518 3.44174,3.3319 5.68762,4.2392 3.12702,1.2631 22.75157,1.4763 43.15146,1.4245 20.73025,-0.053 38.09531,-0.3244 38.91512,-0.4876 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path462" d="m 518.18635,634.34636 c -2.0133,-0.74316 -4.7444,-2.43786 -6.06913,-3.766 -2.24227,-2.24804 -2.45006,-3.20634 -3.00903,-13.87724 -0.37592,-7.17651 -1.34402,-14.09008 -2.5891,-18.48986 -4.49032,-15.86754 -5.9821,-36.98433 -3.75165,-53.1062 0.55771,-4.0312 2.23996,-12.10143 3.73832,-17.93387 2.04085,-7.94409 2.72517,-12.76287 2.72779,-19.20823 0.003,-6.76442 0.37876,-9.22079 1.75882,-11.48976 3.34452,-5.49877 13.94314,-8.16727 17.96065,-4.52211 1.70953,1.55109 1.77236,4.0545 1.77236,70.62081 0,53.82758 -0.25772,69.36608 -1.17129,70.61868 -1.62169,2.2235 -6.99289,2.76866 -11.36774,1.15378 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path466" d="m 532.33814,562.77279 v -19.58771 l 0.74345,0.53648 c 1.46593,1.05782 3.20996,1.86326 4.03453,1.86326 h 0.83922 v 17.02133 17.02133 l -1.42098,0.35872 c -0.78154,0.19731 -2.04541,0.81224 -2.8086,1.36651 l -1.38762,1.00777 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path468" d="m 552.92579,605.12795 c -4.61024,-3.77319 -9.57996,-11.63826 -12.26532,-19.41107 l -1.21822,-3.52618 -0.0956,-18.65027 -0.0956,-18.65026 0.82611,-3.11181 c 2.00396,-7.54852 7.57379,-16.9297 12.61547,-21.24804 0.99001,-0.84797 1.87129,-1.47031 1.9584,-1.38298 0.0871,0.0873 0.12066,19.78469 0.0746,43.7719 l -0.0838,43.61311 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path470" d="m 554.24531,1059.9811 c -0.38562,-0.075 -1.29674,-1.1158 -1.37849,-1.5742 -0.0387,-0.2167 -0.0553,-12.8432 -0.037,-28.0588 l 0.0333,-27.6647 0.4632,-0.4756 c 0.38607,-0.3964 1.36731,-0.5813 1.75961,-0.5842 0.0482,-4e-4 -0.29526,13.0536 -0.29526,29.1581 0,23.3551 -0.0295,29.2776 -0.14603,29.2649 -0.0803,-0.01 -0.26001,-0.038 -0.39932,-0.065 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path472" d="m 620.42769,1013.2884 c -3.57448,-0.8725 -8.96012,-1.3788 -9.30569,-4.7082 l -0.67815,-2.0055 -0.25138,-4.2445 0.41829,-28.18567 c 0.29654,-19.98156 0.0411,-31.19328 0.50411,-32.91713 0.89622,-3.33689 2.97585,-6.44453 6.44362,-8.30431 2.42416,-1.3001 4.38417,-2.04911 12.31933,-2.04911 7.87316,0 9.30668,0.50275 11.63947,1.76142 3.17156,1.71124 4.95339,4.25793 5.90801,6.78394 1.14299,3.02444 0.95659,63.49706 -0.2043,66.28266 -1.21207,2.9084 -4.61574,6.4491 -8.13563,7.3377 -1.79168,0.4523 -6.47414,0.5577 -10.75587,0.4249 -3.25525,-0.101 -6.55619,0.1522 -7.90181,-0.1762 z m 0.80576,-24.14851 c 1.16322,-0.59784 3.35864,-1.93991 4.87872,-2.98238 2.69355,-1.84722 2.34692,-3.71595 2.76767,-2.38687 0.63441,2.00401 4.72774,5.3999 7.58335,4.8628 4.05952,-0.76353 5.0585,-2.82168 5.0585,-10.42179 v -6.53615 h -11.56483 l -11.51834,-0.0293 -4.7e-4,2.21816 0.0337,2.30803 4.63541,-0.0188 c 2.73527,-0.0111 4.24552,-0.44405 4.73547,-0.17155 0.39185,0.21794 0.0185,1.05358 -0.0712,1.68697 -0.14172,1.00046 -0.53695,2.34895 -3.53063,4.29524 -4.24127,2.7574 -5.67341,3.26403 -5.67341,5.70376 0,2.93489 -0.17135,2.93009 2.66607,1.47192 z m 8.72451,-20.28022 c 0.99255,-0.85681 2.35557,-3.3221 3.20525,-5.79732 1.14206,-3.32696 1.57736,-4.85966 2.57572,-4.85966 1.01595,0 1.82378,0.89997 1.98484,2.8501 0.17554,2.12547 -0.11777,2.73658 -1.58921,3.40873 -1.04809,0.47877 -1.79454,1.18693 -1.5773,1.75451 0.19578,0.5115 0.35596,1.50192 0.35596,2.20091 0,2.45771 4.7924,0.83849 6.32761,-2.13792 1.93784,-3.75702 0.66824,-10.20362 -2.32592,-11.81016 -2.08149,-1.11685 -5.66885,-0.79036 -7.54137,0.68637 -1.06893,0.84298 -1.92531,2.93981 -2.5499,5.09386 -1.30345,4.49527 -2.63948,5.88742 -4.17433,5.29693 -2.96077,-1.13908 -2.57455,-6.88848 0.56458,-7.67838 1.60085,-0.40282 2.28581,-2.23765 1.18075,-3.98616 -0.8873,-1.40395 -4.41318,-0.29463 -6.33262,1.99237 -1.36577,1.62731 -1.66572,2.67452 -1.64657,5.7486 0.0129,2.06736 0.41734,4.47138 0.8988,5.34228 1.94785,3.52339 7.593,4.52842 10.64371,1.89494 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00c8e8;fill-opacity:.992157;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path474" d="m 632.81036,983.17958 c -0.63556,-0.67826 -0.71845,-1.13691 -0.71845,-3.9753 v -3.20858 h 2.64339 2.64339 v 3.10243 c 0,2.63704 -0.10273,3.23338 -0.68483,3.97531 -0.91474,1.16589 -2.84114,1.21855 -3.8835,0.10614 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path476" d="m 614.90041,611.55893 c -5.47818,-3.70126 -5.46194,-5.62841 -5.47319,-39.94991 -0.01,-29.83751 0.23875,-32.42084 2.03054,-35.3673 2.73782,-4.50213 9.7432,-6.34849 18.29821,-6.34849 8.55502,0 14.93848,1.49439 17.6763,5.99652 1.78955,2.94276 1.41474,6.84185 1.41806,36.21097 0.003,28.17503 0.0839,31.98162 -1.47142,34.88922 -2.76995,5.17816 -6.88103,7.15268 -17.83149,7.15268 -8.29531,0 -11.8731,-0.70953 -14.64701,-2.58369 z m 8.18551,-25.73237 v -5.15343 h 9.34579 9.34579 v -2.81096 -2.81096 h -11.68224 -11.68224 v 7.96439 c 0,7.87069 -0.17512,7.83539 2.13383,7.83539 2.209,0 2.53907,-0.1521 2.53907,-5.02443 z m 7.19177,-16.60471 c 0.18831,-0.0366 0.45055,-0.54459 0.6657,-0.86103 0.6596,-0.97009 1.35497,-2.74044 1.9953,-4.67326 1.56982,-4.73845 3.62862,-5.98608 4.17546,-2.25932 0.17631,1.20159 -0.48112,2.61937 -1.34586,2.95206 -1.97767,0.76085 -1.99781,5.98598 -0.0231,5.98598 2.81061,0 6.03228,-4.36968 6.03228,-8.18181 0,-2.26738 -0.66708,-3.89433 -1.4774,-5.16066 -1.05092,-1.64231 -2.52443,-2.58631 -4.9728,-2.58631 -4.07241,0 -5.67625,1.85418 -7.32959,7.01759 -1.35947,4.24563 -2.76574,4.90543 -4.63024,3.03612 -1.76893,-1.77348 -2.21107,-4.65285 0.27445,-5.44376 1.94089,-0.6176 3.84262,-4.09021 2.19133,-5.11339 -0.54505,-0.33773 -2.20902,-0.10822 -3.69771,0.51 -2.80301,1.16403 -4.21198,4.73237 -4.21865,8.18117 -0.005,2.38104 0.56756,4.70512 2.18461,6.14168 2.68538,2.38566 6.4958,1.17087 9.91016,0.5067 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path480" d="m 583.49685,1194.3213 c -2.63205,-2.6388 -2.64339,-4.417 -2.64339,-414.70449 l 0.91025,-380.56509 0.0768,-32.0953 2.17287,-2.77511 c 2.35098,-3.00257 4.18121,-2.02246 45.18478,-2.02246 39.9348,0 42.75186,0.15622 45.67967,2.53317 l 2.95718,2.71194 0.16306,412.16132 -0.67534,412.51752 -2.4449,2.3556 c -2.71646,2.6173 -5.74931,2.5331 -45.92889,2.5331 -41.04641,0 -42.91748,-0.1091 -45.45206,-2.6502 z m 81.84368,-7.4058 3.14423,-4.037 0.0827,-66.2535 -0.39676,-66.5434 -2.26148,-3.3325 -3.88235,-2.7418 -32.27071,-0.7473 -32.79612,1.1063 -3.61057,2.1462 -3.24416,3.2525 v 66.7245 c 0,51.3889 0.37971,67.2017 1.65212,68.8007 3.62406,4.5542 6.83181,4.9751 38.22774,5.0155 l 30.77046,-0.8736 z m -24.61354,-173.581 c 7.9414,-2.7755 8.14807,-3.0866 8.14807,-41.16306 0,-32.95752 -0.10203,-35.06928 -2.67771,-37.65159 -1.48289,-1.48673 -4.16023,-2.90576 -5.99586,-3.60546 -4.95757,-1.88972 -17.0157,-1.44776 -22.15047,0.7032 -8.08162,3.38542 -8.9198,5.00242 -8.9198,40.79416 0,20.04755 0.002,33.57605 0.88389,35.22855 2.69585,5.0502 9.31002,6.769 18.65804,6.7743 4.79831,0 9.81254,-0.2968 12.05384,-1.0801 z m -1.58398,-140.068 c 5.13925,-3.46846 7.09546,-8.3228 6.85914,-13.07417 -0.16881,-3.39392 -1.37155,-6.53272 -4.41417,-9.45525 -6.97318,-6.69795 -19.07399,-5.59067 -24.94988,1.89858 -3.21578,4.09873 -3.22084,12.29018 -0.22077,16.5844 4.76762,6.82428 15.50209,8.92162 22.72568,4.04644 z m -1.36978,-61.94554 c 2.03057,-1.08953 2.55651,-2.80695 2.55651,-8.34813 0,-3.83703 -0.71372,-7.69196 -1.58604,-8.56653 -0.87232,-0.87457 -4.9167,-1.59012 -8.98752,-1.59012 -4.07082,0 -8.11521,0.71555 -8.98753,1.59012 -2.57798,2.58462 -2.032,15.24407 0.72693,16.85513 3.02779,1.76807 13.02528,1.80463 16.27765,0.0595 z m 0.46587,-39.18559 c 3.0003,-1.1543 3.0003,-15.78846 0,-16.94275 -3.66595,-1.41039 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87456 -1.58603,4.33307 -1.58603,7.68557 0,3.35251 0.71371,6.81101 1.58603,7.68558 1.64502,1.64926 13.8045,2.19618 17.47045,0.7858 z m 0,-39.75299 c 3.0003,-1.15429 3.0003,-15.78845 0,-16.94275 -3.66595,-1.41038 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87457 -1.58603,4.33307 -1.58603,7.68558 0,3.3525 0.71371,6.81101 1.58603,7.68557 1.64502,1.64926 13.8045,2.19619 17.47045,0.7858 z m 0.5046,-39.21368 c 0.87232,-0.87457 1.58604,-4.72951 1.58604,-8.56653 0,-8.09257 -1.7702,-9.71984 -10.57356,-9.71984 -8.80337,0 -10.57356,1.62727 -10.57356,9.71984 0,3.83702 0.71371,7.69196 1.58603,8.56653 0.87232,0.87457 4.91671,1.59012 8.98753,1.59012 4.07082,0 8.1152,-0.71555 8.98752,-1.59012 z m 6.9047,-82.58433 3.07071,-4.493 0.86249,-33.57673 c 0.56571,-22.02292 -0.51063,-35.24838 -1.42808,-36.96705 -2.15439,-4.03588 -9.35774,-6.42677 -19.34616,-6.42125 -10.21122,0.005 -16.75549,3.01486 -18.90955,8.69506 -0.70882,1.86912 -1.28875,17.83614 -1.28875,35.48223 0,27.49791 0.30761,32.52415 2.15212,35.16432 3.58912,5.1374 9.29638,6.89527 20.679,6.36923 9.16778,-0.42368 10.69887,-0.88197 14.20822,-4.25281 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path486" d="m 594.24699,1187.7985 c -1.15909,-0.1861 -2.79951,-1.1442 -3.68761,-2.2365 -1.49488,-1.8388 -1.31131,-8.5525 -1.33055,-68.6798 -0.0137,-42.7931 0.73515,-65.8381 1.58418,-66.8831 3.33535,-4.1049 5.06117,-6.6424 37.3562,-6.6424 19.85047,0 32.4974,1.49 33.95204,2.1545 1.22428,0.5593 4.03684,3.0392 4.89282,4.492 1.41138,2.3954 0.57113,8.6669 0.57113,67.039 v 64.367 l -1.93649,3.9919 -4.71377,2.9045 -30.90991,1.6993 c -20.82649,1.1449 -30.73945,-1.3974 -32.14976,-1.6239 z m 48.27939,-26.876 9.82832,-16.6722 -10.49871,-1.2375 c -6.93861,-0.8179 -18.12085,-0.1436 -24.74598,0 l -11.47394,0.261 12.08666,19.2791 c 6.72092,10.7203 12.32443,15.8272 12.69104,15.4321 0.3666,-0.3951 5.92627,-6.5684 12.11261,-17.0625 z m -0.87571,-43.3626 c 6.55374,-10.4749 10.57311,-17.3167 10.57311,-17.6433 0,-0.3266 -9.16284,-0 -22.78434,-0 -13.62149,0 -21.69277,-0.5851 -21.69277,-0.3178 0,0.5187 19.89711,32.7103 21.45728,34.6835 0.50934,0.6442 -2.27865,3.5495 0.11007,1.4228 1.38644,-1.2344 5.78291,-7.6659 12.33665,-18.1408 z m 1.13238,-46.0729 c 6.22721,-9.9106 9.27066,-15.806 9.27066,-16.0734 0,-0.2673 -9.26032,-0.7017 -22.88182,-0.7017 -13.62149,0 -24.20351,-0.744 -24.20351,-0.5285 0,0.3071 12.54336,18.6285 23.50069,35.8728 1.17961,1.8564 -2.07666,-0.013 -1.06964,-1.0847 0.66128,-0.7037 9.15641,-7.5738 15.38362,-17.4845 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path488" d="m 627.22564,1086.2996 c -1.36595,-2.1565 -6.28035,-9.9327 -10.92087,-17.2805 l -8.43732,-13.3596 21.71147,-0.1218 c 11.9413,-0.067 21.793,-0.04 21.89266,0.06 0.16849,0.1689 -20.53294,33.2929 -21.37902,34.2082 -0.21085,0.2281 -1.50096,-1.3497 -2.86692,-3.5061 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path490" d="m 618.93991,1117.4616 c -5.9568,-9.4452 -10.74845,-17.2554 -10.6481,-17.356 0.10035,-0.1006 9.87754,-0.1281 21.7271,-0.061 l 21.54464,0.1219 -10.771,17.1 c -5.92405,9.405 -10.82749,17.1603 -10.89655,17.2341 -0.069,0.074 -4.99929,-7.5937 -10.95609,-17.0389 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path492" d="m 627.34816,1175.0783 c -1.29113,-2.0355 -6.20112,-9.8147 -10.91108,-17.2872 l -8.56357,-13.5863 21.70844,-0.1218 c 11.93964,-0.067 21.76048,0.1196 21.89378,0.064 1.66501,-0.694 -20.53797,33.3157 -21.38241,34.2108 -0.2266,0.2401 -1.40744,-1.1705 -2.74516,-3.2795 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path494" d="m 705.333,475.35062 0.58572,-25.61496 h 2.58935 c 1.42413,0 3.07073,-0.1852 3.6591,-0.41156 6.23384,-2.39832 6.66628,-39.81075 0.51622,-44.66085 -0.98323,-0.7754 -2.60578,-1.09079 -4.08546,-1.11196 l -3.02606,-0.0433 0.17046,-24.49951 c 0.17521,-25.18178 -0.45706,-26.64286 -3.3757,-33.56049 -0.60015,-1.42246 -0.95981,-2.71801 -0.79924,-2.87899 0.73296,-0.73484 6.77569,9.79438 11.3051,19.6987 8.03987,17.58051 12.92059,24.16575 20.92458,28.23212 5.97386,3.03498 10.12842,3.56131 28.19456,3.57187 l 16.75248,0.01 2.24689,2.25266 c 1.28725,1.29057 2.24478,2.91766 2.24196,3.80967 -0.006,1.78302 -4.60673,10.12411 -8.86443,16.06984 -5.1397,7.17741 -13.21804,16.43802 -27.76099,31.82387 -25.38008,26.85109 -32.85153,36.30476 -38.78153,49.07044 l -2.48145,7.83399 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path496" d="m 551.50149,411.19136 c -0.98602,-0.57578 -1.10996,-1.3398 -1.10661,-6.82131 0.002,-2.873 0.0677,-5.46502 0.14652,-5.76006 0.20727,-0.77576 1.25515,-1.22041 2.87607,-1.22041 h 1.41347 v 7.0274 7.02739 l -1.46028,-0.007 c -0.80316,-0.004 -1.64428,-0.11456 -1.86917,-0.24589 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path498" d="m 705.29823,426.52862 v -21.6925 l 2.74532,0.0832 c 3.12768,0.0948 3.89424,0.4293 4.72483,2.06157 0.61397,1.20659 1.76821,5.63906 2.33099,8.95136 1.27555,7.50746 1.05966,16.78021 -0.57067,24.51085 -1.52786,7.24475 -1.97566,7.77797 -6.53195,7.77797 h -2.69852 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path500" d="m 584.73878,305.9748 c 0.003,-2.26451 1.14147,-4.16777 2.76325,-4.61938 1.23234,-0.34316 46.09771,-0.32639 47.35227,0.0177 0.6001,0.16459 1.31857,0.65313 2.00748,1.36501 1.06534,1.10085 1.37105,1.89697 1.3778,3.58804 l 0.003,0.64418 h -26.75233 -26.75234 l 10e-4,-0.99555 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path502" d="m 744.76749,392.34624 c -7.37403,-1.15256 -12.25912,-3.51316 -17.18139,-8.30249 -4.19,-4.07684 -9.97636,-11.23159 -14.15429,-20.84415 -6.80877,-15.6656 -12.32942,-19.2518 -16.1565,-24.99405 -0.5827,-0.8743 -3.10009,-5.66604 -4.55833,-7.29974 -3.50425,-3.92592 -5.49316,-5.94965 -6.99245,-7.1149 -0.67792,-0.52688 -2.15819,-0.77779 -2.10637,-0.82975 0.1682,-0.16863 10.68177,1.9607 15.83895,3.44149 6.54031,1.87794 9.83649,2.91531 21.26168,6.69147 24.21778,8.00427 37.13651,11.3397 48.9486,12.63781 1.92757,0.21183 4.08294,0.48465 4.78972,0.60624 4.01962,0.69158 8.00385,4.57809 8.87032,8.65275 0.19483,0.9162 0.25245,4.67159 0.19948,13.00069 l -0.0745,11.71234 -0.63074,1.34936 c -0.80435,1.72076 -2.07559,3.36646 -5.20034,6.73215 -1.37555,1.48161 -2.82564,3.19454 -3.22244,3.80651 l -0.72144,1.11267 -13.45364,-0.0227 c -9.97413,-0.0168 -13.9716,-0.10364 -15.45634,-0.33571 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path926" d="m 626.42004,812.0638 c -3.0151,-0.30334 -4.96457,-1.13982 -5.58976,-2.2103 -1.31153,-2.24565 -1.63054,-9.94619 -0.65837,-13.08723 0.61716,-1.99402 1.1237,-2.59841 3.95631,-3.1346 3.07565,-0.5822 10.37998,-0.38743 12.68678,0.34496 1.50914,0.47914 1.69385,0.57767 2.14224,1.78531 0.74868,2.0164 1.22658,7.31549 0.8778,10.29605 -0.36136,3.08801 -0.86268,4.19746 -2.35622,4.92047 -2.0881,1.01083 -7.02388,1.49128 -11.05878,1.08534 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path928" d="m 626.45483,772.42523 c -1.19582,-0.13489 -3.06338,-0.4663 -3.83508,-0.72229 -1.34222,-0.44525 -1.84952,-0.79471 -2.34633,-2.1889 -0.75897,-2.1299 -0.65153,-9.67076 0.10744,-11.80066 0.64277,-1.8038 1.39271,-2.22659 4.72627,-2.66451 2.84021,-0.37312 11.47273,-0.10592 12.66771,0.35154 1.51479,0.57988 2.20815,3.48226 2.20178,8.48923 -0.004,3.1328 -0.28379,5.81187 -0.98109,6.87608 -0.21326,0.32548 -1.09366,1.1394 -1.83309,1.33166 -1.62821,0.42336 -7.87645,0.64719 -10.70761,0.32785 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path930" d="m 626.45219,732.49906 c -1.25777,-0.13165 -3.14347,-0.41083 -3.92609,-0.67038 -1.36508,-0.45271 -1.72145,-0.63254 -2.21967,-2.03069 -0.75897,-2.1299 -0.78566,-9.66466 -0.0267,-11.79456 0.64277,-1.8038 1.59031,-2.26853 4.92387,-2.70646 2.84021,-0.37311 11.2883,-0.0856 12.48328,0.3719 1.51479,0.57988 2.27239,3.48197 2.26602,8.48895 -0.004,3.1328 -0.58408,6.09459 -1.28138,7.1588 -0.21517,0.32839 -0.84775,0.6853 -1.5938,0.87529 -1.65266,0.42087 -7.69669,0.6137 -10.62554,0.30715 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path932" d="m 625.65956,693.89955 c -0.97518,-0.13612 -2.55333,-0.0903 -3.32293,-0.34698 -1.37509,-0.45857 -1.53415,-0.83609 -2.02375,-2.39853 -0.34888,-1.1134 -0.57835,-2.85799 -0.67551,-5.5487 -0.2167,-6.00139 0.52022,-7.93082 3.07167,-9.20691 1.28365,-0.64201 1.83934,-1.06269 7.10382,-1.06269 5.37865,0 5.54929,0.20323 7.00626,0.91889 1.84975,0.90844 2.42826,1.87471 2.83202,4.71762 0.53225,3.74752 -0.17476,11.16443 -1.26107,12.14752 -1.12933,1.02204 -8.85213,1.32114 -12.73051,0.77978 z"/><path id="path489" d="m 379.06905,101.33936 h 13.1901 l 0.037,-8.25531 h 14.1068 c 3.694,0 4.8671,3.29254 4.8671,8.2606 v 75.70196 c 0,3.53235 -3.4085,6.31095 -6.4405,6.31095 h -9.5226 c -2.5944,0 -2.7443,-2.75044 -3.0117,-5.11156 v -5.02502 h -13.0052 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 392.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 320.74985,56.29539 v 15.94604 h 43.5888 V 56.01064 c 0,-2.09826 -1.8726,-3.04523 -3.5597,-3.4883 -12.173,-3.19604 -25.2766,-3.03408 -36.8326,0 -1.8219,0.47838 -3.1965,1.67683 -3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 278.71645,200.68211 c -1.8116,5.3094 -14.3159,15.23177 -26.804,17.54252 0,3.02085 2.1746,7.20824 6.6781,7.20824 h 42.9453 c 9.0444,0 6.7685,24.00009 -7.8827,24.00009 h -14.8228 c -30.7958,10.32445 -58.299,10.53516 -88.3562,0 h -15.6167 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12586 c 6.109,0 8.9689,-3.48568 8.6104,-7.02445 -10.9644,-3.70415 -20.7546,-8.55799 -26.2816,-17.58519 v -3.35273 h 87.2518 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 274.17465,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.5651,3.68761 5.8562,3.68761 17.7306,0.98444 39.2718,0.92676 57.4315,0 3.0517,0 6.0443,-1.82692 6.0104,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="m 258.08445,225.33728 h -45.0418"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 355.50055,191.92715 v 11.14596 c 0,0.96002 -0.737,2.03381 -1.3112,2.03381 h -23.0257 c -0.7228,0 -1.5998,-1.11889 -1.5998,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="m 252.26535,218.07198 h -35.7635"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 128.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27175,0.92888 57.43165,0 3.0517,0 6.0443,-1.83107 6.0102,-3.7933 v -7.74857 h -69.29782 z"/><path id="path509" d="m 91.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 v -58.65862 c 4.57443,-17.00507 13.35533,-35.47833 41.84537,-41.00408 4.97535,0 7.55529,-4.59359 7.55529,-7.40352 26.96999,-35.0496 56.25477,-53.08707 86.30587,-65.49263 h 63.6397 c 27.3731,12.02627 42.6345,29.98675 54.6313,49.5466 V 61.9055 c 0,4.46695 3.7756,9.11203 8.7178,9.11203 h 52.8878 v 128.70726 z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 100.1578,95.57843 H 327.54875 C 327.43015,49.18358 304.14675,1.15062 259.36955,1.15062 L 195.76105,1.8971 C 133.48741,13.03019 120.68895,56.85936 100.1578,95.57843 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 81.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.3167,23.51364 -23.9962,23.51364 H 97.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 216.49175,61.4392 v -1.87954 l 5.5759,-6.74897 c 3.0668,-3.71194 5.5759,-6.75827 5.5759,-6.76966 0,-0.0114 -2.2283,-0.0205 -4.9515,-0.0205 h -4.9514 v -1.75092 -1.75094 h 7.7716 7.7718 v 1.61419 1.61418 l -5.8379,7.04557 -5.8376,7.04554 6.0529,0.0114 6.0532,0.0114 v 1.7297 1.72968 h -8.6113 -8.6116 v -1.87951 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 236.52525,52.97079 V 42.61137 h 2.6255 2.6254 v 8.6079 8.60791 h 6.5824 6.5825 v 1.75151 1.75152 h -9.2079 -9.2079 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 227.42615,152.06817 v -10.42336 h 2.4583 2.4584 v 8.66103 8.66102 h 6.1635 6.1634 v 1.76236 1.76232 h -8.6218 -8.6218 z"/></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg b/src/Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg
deleted file mode 100644
index c073c9c0..00000000
--- a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000 1300" xml:space="preserve"><metadata id="metadata161"/><style id="style2" type="text/css">.st0{opacity:.1}.st1{fill:#02c5e5}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><g id="layer1"><g id="g344" transform="translate(-64,299.7467)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="237.9 448.9 225.8 469.9 250 469.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="250 605.9 237.9 626.9 225.8 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="169.9 525.8 148.9 537.9 169.9 550" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="326.9 537.9 305.9 550 305.9 525.8" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="M 389.22472,464.93186 V 72.687962 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-3"/></g><g id="g315" transform="translate(56.713,299.7467)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-6"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><path id="path4136" d="m 680.8329,101.33936 h -13.19009 l -0.0372,-8.255307 h -14.10678 c -3.694,0 -4.86707,3.292534 -4.86707,8.260597 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 667.63443,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 739.15217,56.29539 v 15.946041 h -43.5888 V 56.010642 c 0,-2.098267 1.87258,-3.045238 3.55963,-3.488308 12.17302,-3.196036 25.27663,-3.034074 36.83267,0 1.82189,0.478381 3.1965,1.676837 3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 781.18551,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 785.72736,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 801.81755,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 704.71423,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 807.6366,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 931.20675,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 858.45697,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 968.76047,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.478328 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.593593 -7.55529,-7.403519 C 917.38071,31.981408 888.09597,13.94394 858.0448,1.5383817 H 794.40512 C 767.03205,13.564651 751.77061,31.525124 739.77382,51.084979 v 10.820524 c 0,4.466942 -3.77561,9.112021 -8.71777,9.112021 H 678.16828 V 199.72479 Z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 959.74418,95.578426 H 732.35325 C 732.47179,49.183575 755.75521,1.15062 800.53245,1.15062 l 63.60853,0.7464785 c 62.27359,11.1330875 75.07205,54.9622645 95.6032,93.6813275 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 978.40756,126.18349 H 730.44883 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 815.30427,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 824.38936,52.916016 V 42.513284 l 5.50031,0.01822 c 5.86555,0.01821 5.99551,0.02347 7.21251,0.236844 0.72764,0.127791 1.2063,0.273954 1.73262,0.529704 0.56119,0.272632 0.92919,0.536857 1.3444,0.965169 0.6865,0.708209 1.17119,1.612413 1.4232,2.655056 0.10465,0.436493 0.11392,0.546291 0.11623,1.401798 6.9e-4,0.725362 -0.0233,1.008267 -0.0743,1.294521 -0.49307,2.372679 -2.15713,3.863382 -4.92053,4.408664 -0.52052,0.102747 -0.58004,0.12279 -0.5089,0.173128 0.044,0.0312 0.27805,0.18384 0.51935,0.338992 1.26535,0.81414 2.04879,1.63119 3.24347,3.383274 0.43519,0.6382 3.38993,5.242662 3.43201,5.348069 0.0233,0.04234 -0.49075,0.05101 -2.51118,0.04215 l -2.53257,-0.0114 -1.89628,-2.766293 c -2.70088,-3.939608 -3.00426,-4.356325 -3.57776,-4.912496 -0.79112,-0.767048 -1.35952,-0.94266 -3.17329,-0.980344 L 828.653,54.61555 v 4.3512 4.351165 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.663034 c 0.70021,-0.07582 1.02521,-0.153763 1.4046,-0.337001 0.60955,-0.294507 1.03662,-0.843043 1.20307,-1.545677 0.0907,-0.379282 0.0884,-1.172853 -0.002,-1.51464 -0.27525,-1.037227 -1.09727,-1.677094 -2.30428,-1.793635 -0.22549,-0.02279 -1.74122,-0.03988 -3.36922,-0.04055 l -2.96011,-0.0016 v 2.663058 2.663038 l 2.78783,-0.02279 c 1.66078,-0.01369 2.97079,-0.0419 3.23998,-0.07107 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 804.36779,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path id="path489" d="m 314.06908,101.33936 h 13.19009 l 0.0372,-8.255307 h 14.10678 c 3.694,0 4.86707,3.292534 4.86707,8.260597 v 75.70196 c 0,3.53235 -3.40852,6.31095 -6.44045,6.31095 h -9.52259 c -2.5944,0 -2.74434,-2.75044 -3.01169,-5.11156 v -5.02502 H 314.2902 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 327.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 255.74981,56.29539 v 15.946041 h 43.5888 V 56.010642 c 0,-2.098267 -1.87258,-3.045238 -3.55963,-3.488308 -12.17302,-3.196036 -25.27663,-3.034074 -36.83267,0 -1.82189,0.478381 -3.1965,1.676837 -3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 213.71647,200.68211 c -1.81167,5.3094 -14.31597,15.23177 -26.80398,17.54252 0,3.02085 2.17456,7.20824 6.67803,7.20824 h 42.94533 c 9.04439,0 6.76848,24.00009 -7.88272,24.00009 h -14.82275 c -30.79579,10.32445 -58.29906,10.53516 -88.35628,0 h -15.61665 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12588 c 6.10893,0 8.96884,-3.48568 8.61035,-7.02445 -10.9644,-3.70415 -20.75456,-8.55799 -26.28159,-17.58519 v -3.35273 h 87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 209.17462,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.56512,3.68761 5.85626,3.68761 17.73054,0.98444 39.27177,0.92676 57.43145,0 3.05168,0 6.04433,-1.82692 6.01039,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="M 193.08443,225.33728 H 148.04265"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 290.50058,191.92715 v 11.14596 c 0,0.96002 -0.73701,2.03381 -1.3112,2.03381 h -23.02573 c -0.72278,0 -1.59984,-1.11889 -1.59984,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="M 187.26538,218.07198 H 151.50187"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 63.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27172,0.92888 57.43168,0 3.05166,0 6.04429,-1.83107 6.01013,-3.7933 v -7.74857 H 63.69523 Z"/><path id="path509" d="m 26.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 V 115.43861 C 5.72505,98.43354 14.50595,79.960282 42.99599,74.43453 c 4.97535,0 7.55529,-4.593593 7.55529,-7.403519 26.96999,-35.049603 56.25473,-53.087071 86.3059,-65.4926293 h 63.63968 c 27.37307,12.0262693 42.63451,29.9867423 54.6313,49.5465973 v 10.820524 c 0,4.466942 3.77561,9.112021 8.71777,9.112021 H 316.7337 V 199.72479 Z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 35.1578,95.578426 H 262.54873 C 262.43019,49.183575 239.14677,1.15062 194.36953,1.15062 L 130.761,1.8970985 C 68.48741,13.030186 55.68895,56.859363 35.1578,95.578426 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 16.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.31669,23.51364 -23.99616,23.51364 H 32.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 151.49179,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 171.52526,52.970786 V 42.611364 h 2.62547 2.62545 v 8.607904 8.607907 h 6.5824 6.58243 v 1.751518 1.751517 h -9.20788 -9.20787 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 162.42612,152.06817 v -10.42336 h 2.45836 2.45836 v 8.66103 8.66102 h 6.16349 6.16346 v 1.76236 1.76232 h -8.62185 -8.62182 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path979" d="m 724.21326,200.03615 v 6.10386 h 9.9129 V 199.759 Z"/></g></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg b/src/Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg
deleted file mode 100644
index f4f12514..00000000
--- a/src/Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st0{opacity:.1}.st2{fill:#fff}</style><style id="style2-6" type="text/css">.st0{opacity:.1}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path139" d="m 336.48913,612.01334 c -4.48491,-0.96172 -17.26511,-2.20937 -14.21934,-5.20076 l -1.59612,-5.33256 4.69156,-28.97943 c -21.87609,0.35049 0.88574,-29.59975 1.14094,-31.15228 0.67186,-4.0867 0.63712,-6.98639 4.0089,-9.33254 4.31967,-3.0057 6.13876,-6.05239 15.39769,-6.04934 6.18575,0.002 6.23657,4.51842 7.63527,4.8094 2.83752,0.59027 9.26915,0.22171 11.12017,2.22098 1.29357,1.39718 -1.70326,4.54462 -1.05568,6.52843 l 0.45372,1.38995 3.01931,28.03144 c 2.5809,23.96121 -1.28772,28.6331 -1.52389,30.69067 -0.50713,4.41767 -1.36999,7.75168 -2.71808,9.24386 -0.75196,0.83233 -6.13557,2.17746 -7.4235,2.75447 -0.6956,0.31163 -1.65288,2.59566 -4.83555,2.70854 -6.19176,0.21959 -12.78623,-2.05009 -14.09542,-2.33083 z m 7.03011,-22.69305 c 2.05969,-1.10868 2.82647,-2.34895 4.0826,-6.60361 0.94044,-3.18536 1.27937,-3.92467 2.00093,-4.36459 0.80192,-0.48891 1.26549,-0.45046 1.96409,0.16291 0.71152,0.62473 1.00895,1.51574 1.00895,3.02259 0,1.56253 -0.45686,2.45036 -1.57367,3.05821 -0.47337,0.25764 -0.98442,0.46843 -1.13567,0.46843 -0.46699,0 -0.51735,0.31657 -0.38564,2.42443 l 0.12741,2.03924 0.99608,-0.11707 c 1.81227,-0.21299 3.67586,-1.28059 4.58801,-2.62833 0.73213,-1.08177 1.05118,-2.01238 1.28038,-3.73464 0.52157,-3.91942 -0.80021,-7.14962 -3.48153,-8.50821 -0.95096,-0.48184 -1.18331,-0.52396 -2.89025,-0.52396 -1.61522,0 -1.95941,0.0547 -2.65165,0.42127 -2.42724,1.2854 -3.01034,2.27706 -4.76741,8.10775 -0.81484,2.70397 -1.68257,3.5027 -3.32487,3.06047 -0.81096,-0.21836 -1.7952,-1.15122 -2.09882,-1.98922 -0.27463,-0.75801 -0.29371,-2.48144 -0.0369,-3.33844 0.11098,-0.37041 0.44343,-0.96663 0.73878,-1.32494 0.5549,-0.6732 2.03724,-1.48499 2.71713,-1.48802 0.21302,-8.8e-4 0.44057,-0.0879 0.50566,-0.19321 0.0651,-0.10531 0.0206,-1.09911 -0.0989,-2.20844 l -0.21726,-2.01697 -0.73033,0.1088 c -1.04346,0.15545 -2.73301,0.73031 -3.56485,1.21291 -1.00575,0.5835 -2.3307,2.05885 -2.82441,3.14502 -0.60372,1.32822 -0.8601,3.09117 -0.73888,5.08087 0.2291,3.76062 1.69285,6.01606 4.59237,7.07626 0.73645,0.26928 1.31213,0.32792 2.86609,0.29196 1.83004,-0.0424 2.0098,-0.0801 3.05264,-0.64147 z m 12.41532,-19.9635 v -2.27241 l -4.3514,-0.0924 c -4.61309,-0.098 -4.53528,-0.082 -4.77362,-0.9766 -0.38253,-1.43579 0.87656,-2.86072 4.54388,-5.14234 1.30429,-0.81146 2.86862,-1.78392 3.47629,-2.16102 l 1.10485,-0.68564 v -2.47936 c 0,-1.37252 -0.0718,-2.47937 -0.16095,-2.47937 -0.2065,0 -2.12366,1.07629 -5.14235,2.88691 -1.67092,1.00223 -2.71254,1.76796 -3.47394,2.55381 l -1.08745,1.12238 -0.2181,-0.6741 c -0.55224,-1.70685 -1.65782,-3.08363 -3.04416,-3.79088 -0.90425,-0.46132 -2.76434,-0.67068 -4.28507,-0.4823 -2.32805,0.28839 -4.02881,1.54469 -4.62261,3.41459 -0.2868,0.90314 -0.54591,5.91584 -0.57837,11.18885 l -0.0144,2.34229 h 11.3137 11.31371 z"/><g id="g315" transform="translate(0,300.03245)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><ellipse id="ellipse382" cx="344.639" cy="859.606" rx="15.571" ry="14.069" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path384" d="m 443.0983,809.82781 v 45.80985" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path386" d="m 436.0092,815.74618 v 36.37333" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path388" d="m 355.92023,980.61127 c -0.159,2.38632 -0.9339,4.18348 -2.3494,5.44717 -1.0538,0.94086 -2.4969,1.60298 -4.1869,1.92092 -0.3864,0.0726 -1.0871,0.1771 -1.0975,0.16314 0,-0.005 -0.093,-0.85306 -0.2017,-1.88773 -0.1082,-1.03464 -0.2053,-1.93454 -0.2156,-1.9998 -0.018,-0.10426 -0.01,-0.11846 0.052,-0.11846 0.1214,0 0.6621,-0.12294 1.0604,-0.24083 1.8948,-0.56173 2.9076,-1.69881 3.1357,-3.52037 0.053,-0.4186 0.023,-1.49252 -0.051,-1.88234 -0.1958,-1.02944 -0.6378,-1.79009 -1.336,-2.30018 -0.5453,-0.39839 -0.9906,-0.54269 -1.6797,-0.54425 -0.4911,0 -0.7649,0.0565 -1.0906,0.22816 -0.224,0.11845 -0.5342,0.39899 -0.7138,0.64552 -0.4284,0.5885 -0.6382,1.17335 -1.3991,3.89925 -0.4752,1.70296 -0.7598,2.51481 -1.1909,3.39834 -0.584,1.19653 -1.3563,2.06447 -2.414,2.7127 -0.5828,0.35721 -1.3337,0.64064 -2.0474,0.7727 -0.3392,0.0631 -0.4902,0.0716 -1.1851,0.0709 -0.6888,-7.5e-4 -0.842,-0.01 -1.1342,-0.0703 -1.7103,-0.34894 -3.1451,-1.32436 -3.9859,-2.70946 -0.3778,-0.62245 -0.6928,-1.42824 -0.8702,-2.22642 -0.3894,-1.7521 -0.3112,-4.07304 0.1924,-5.71076 0.2323,-0.7556 0.6307,-1.54303 1.0637,-2.10262 0.2976,-0.38477 1.0376,-1.06011 1.4626,-1.33492 0.6802,-0.43973 1.5737,-0.79266 2.4151,-0.95396 0.4254,-0.0815 0.9688,-0.14541 1.2361,-0.14541 h 0.1571 l 2e-4,0.18183 c 2e-4,0.0998 0.039,0.97141 0.087,1.93652 0.048,0.96511 0.086,1.80485 0.086,1.86617 l 10e-5,0.11137 -0.3029,0.0565 c -0.6791,0.12626 -1.358,0.40173 -1.7702,0.71779 -0.8027,0.61542 -1.1472,1.52476 -1.1467,3.02784 3e-4,0.9899 0.1461,1.66912 0.5004,2.33009 0.4111,0.76692 0.8552,1.07989 1.5814,1.1146 0.5403,0.0263 0.9144,-0.092 1.2917,-0.40687 0.6036,-0.50373 1.0028,-1.42843 1.6845,-3.90103 0.5306,-1.92496 0.7696,-2.6569 1.1769,-3.6043 0.7236,-1.68302 1.723,-2.76077 3.1653,-3.41339 0.8627,-0.39031 1.6574,-0.56193 2.8045,-0.60571 1.3619,-0.0523 2.6128,0.24529 3.8083,0.90462 1.3364,0.73709 2.2925,1.87859 2.8381,3.38818 0.4756,1.31608 0.6841,3.06752 0.5698,4.78495 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path390" d="m 344.68166,571.55323 -11.22758,0.0524 0.0282,-4.64898 c 0.0146,-2.39871 0.018,-4.79751 0.034,-5.29725 0.1201,-2.99844 0.50834,-4.47151 1.80242,-5.57094 1.43938,-1.29933 3.86276,-1.68857 6.05962,-1.28878 1.22398,0.1999 2.1495,0.86284 2.97159,1.66242 0.75529,0.79959 1.34588,1.99896 1.58337,3.29829 0.053,0.29984 0.0886,0.10698 0.12964,0.007 0.026,0 0.17696,-0.007 0.36596,-0.20693 0.79258,-1.09943 1.50437,-1.8495 2.85325,-2.64909 0.78279,-0.49974 1.13628,-0.74914 4.08763,-2.44826 l 2.49546,-1.39927 0.01,2.39875 c 0,1.99896 -2e-4,2.4987 -0.034,2.4987 -0.023,0 -1.34447,0.89954 -2.93445,1.79907 -4.59312,2.79854 -5.0351,3.37378 -5.57969,3.97346 -0.54019,0.69964 -0.66221,0.81512 -0.69151,2.41429 l 0.48716,0.75844 4.08351,0.26903 4.69846,0.0106 -0.0199,2.16917 0.0199,2.25025 -11.13382,-0.0473 z m -1.74891,-9.39408 c -0.041,-0.69963 -0.114,-1.29932 -0.18719,-1.49922 -0.2217,-0.79958 -0.88159,-1.39927 -1.75178,-1.59917 -0.32459,-0.1 -1.14798,-0.1 -1.50817,-0.1 -0.87379,0.1 -1.48218,0.49974 -1.85017,1.19938 -0.3531,0.69964 -0.3777,0.99948 -0.3791,4.69756 l -7e-4,2.4987 h 2.85636 2.85645 v -2.2988 c 0,-1.29933 -0.018,-2.59865 -0.036,-2.8985 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path392" d="m 333.0763,580.70071 c 0.2699,-3.09839 1.47058,-5.09735 3.82724,-6.39667 0.94539,-0.49974 2.47236,-0.99948 3.66664,-1.09943 h 0.2144 l 0.021,0.1 c 0.037,0.19989 0.41959,3.89797 0.40439,3.89797 -0.01,0 -0.17189,0.1 -0.36389,0.1 -0.1921,0 -0.53819,0.0999 -0.76929,0.1999 -1.79067,0.49974 -2.78005,1.59916 -3.10355,3.19833 -0.099,0.49974 -0.1074,1.59917 -0.015,2.19886 0.1217,0.69964 0.322,1.19938 0.62179,1.59917 0.41149,0.59969 0.98798,0.99948 1.60627,1.19938 0.3497,0.0999 1.05159,0.19989 1.39958,0.0999 0.68299,-0.19989 1.12958,-0.49974 1.53758,-1.29932 0.28619,-0.49974 0.48609,-1.09943 1.12488,-3.39823 0.58179,-2.09891 0.89518,-2.99845 1.46878,-3.99793 0.54769,-0.99948 1.29527,-1.69911 2.25086,-2.2988 1.01618,-0.59969 2.16996,-0.89953 3.44104,-0.79959 1.09519,0 2.11077,0.29985 3.03455,0.89954 0.67949,0.39979 1.15789,0.79958 1.62308,1.49922 0.94818,1.29932 1.41878,2.99844 1.41828,5.09735 -5e-4,2.39875 -0.5283,4.19782 -1.61348,5.59709 -0.28049,0.29984 -0.87698,0.89953 -1.25648,1.09943 -1.02518,0.69963 -2.17746,1.09942 -3.55564,1.19937 -0.2116,0 -0.38909,0 -0.39449,0 -0.015,0 -0.2131,-4.09787 -0.2004,-4.09787 0.01,0 0.1496,-0.0999 0.31999,-0.0999 0.96079,-0.1999 1.73388,-0.59969 2.16607,-1.09943 0.33459,-0.3998 0.56069,-0.89954 0.68789,-1.49922 0.1015,-0.49974 0.1113,-1.69912 0.018,-2.19886 -0.1453,-0.89953 -0.46589,-1.59917 -0.92189,-1.99896 -0.48339,-0.49974 -1.31478,-0.59969 -1.98367,-0.29985 -0.30419,0.0999 -0.66298,0.3998 -0.87728,0.69964 -0.397,0.59969 -0.77619,1.69912 -1.28808,3.59813 -0.61799,2.19886 -1.08688,3.49818 -1.64607,4.49766 -0.90499,1.59917 -2.40657,2.59865 -4.21394,2.99844 -0.65499,0.1 -1.14148,0.1 -1.88937,0.1 -0.52549,0 -0.75938,0 -1.08948,-0.1 -1.82277,-0.39979 -3.39374,-1.29932 -4.32833,-2.69859 -0.65799,-0.99948 -1.07878,-2.19886 -1.27778,-3.79803 -0.053,-0.39979 -0.097,-2.2988 -0.063,-2.6986 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path394" d="m 344.34473,966.1041 h -11.2417 v -2.07865 -2.07863 h 9.3507 9.3505 v -5.19669 -5.19663 h 1.8911 1.8912 v 7.27527 7.27533 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path396" d="m 409.8518,320.05567 -2.8025,-2.94026 -2.1084,-1.796 -3.8978,-2.62047 -4.9398,-2.55642 -3.8113,-1.26102 -3.8729,-0.82355 -1.3897,-0.20254 -2.8884,-0.16657 h -57.7923 l -1.5715,0.14912 -1.7697,0.23885 -1.7748,0.23784 -2.7296,0.54225 -2.3129,0.60501 -2.4432,0.75415 -2.944,0.94164 -2.1288,0.90223 -3.8498,1.71494 -2.7574,1.53514 -2.1058,1.19382 -3.235,2.15931 -2.4201,1.63397 -1.436,1.20278 -1.896,1.44906 -3.2118,2.6021 -2.4228,2.54068 -4.259,4.68887 -2.5995,3.24851 -1.6774,2.6235 -1.271,2.18323 -1.9119,3.72736 -0.727,1.6468 -1.1613,2.96158 -0.6623,2.59781 -0.7848,3.27106 -0.3398,2.68009 -0.048,2.38299 v 3.99567 2.84426 875.03454 l 0.1638,2.4919 0.3452,3.3929 1.2989,4.7686 1.2397,3.7743 3.6049,7.2541 2.5738,4.0559 2.4685,3.1987 1.4819,1.9751 2.6694,2.8626 3.0699,3.022 2.1765,1.9253 4.0187,3.1181 4.1145,2.8537 2.3075,1.2731 3.5235,1.8455 3.6903,1.6798 4.1541,1.4538 3.7259,1.1675 3.6825,0.7441 3.285,0.4416 3.0789,0.2674 h 56.728 l 2.2738,-0.2161 3.6621,-0.6453 2.1372,-0.5088 2.6035,-0.8999 3.7077,-1.5118 3.7208,-1.891 3.1188,-1.9598 2.4944,-2.0592 3.0857,-2.8789 3.1141,-3.8291 2.3879,-3.9155 1.3793,-3.2339 1.0698,-2.9013 0.8145,-3.3519 0.4154,-3.6021 0.024,-2.1424 V 343.15522 l -0.2807,-2.93341 -0.6388,-3.84483 -1.3177,-4.25655 -1.5322,-3.68324 -2.5337,-4.45711 -1.9699,-2.57666 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path398" d="m 395.3929,1180.0491 v 6.0661 l 0.2504,2.2569 -0.22889,0.3633 0.0188,0.4323 0.0368,0.983 -1.0319,1.3186 -1.91624,1.5403 -1.8286,1.4972 -2.1313,1.0814 -1.9039,0.5267 -1.6018,0.1436 h -79.7814 l -1.9951,-0.4092 -2.2181,-0.8515 -1.5437,-0.8939 -1.324,-1.0482 -0.8339,-0.9964 -0.9297,-1.4644 -0.5711,-1.0947 -0.331,-0.8522 -0.2214,-1.445 v -0.9701 -816.23528 l 0.1524,-0.78853 0.1354,-0.61772 0.2239,-0.77581 0.2629,-0.76027 0.5285,-1.02162 0.7718,-1.1054 0.9507,-1.04883 1.5188,-1.1948 1.1498,-0.70115 1.3513,-0.54994 1.7628,-0.48373 1.567,-0.17203 h 79.0926 l 1.0991,0.0989 1.3891,0.27672 2.2207,0.74493 1.1905,0.67498 1.4954,1.14485 0.8938,0.8516 1.1289,1.64893 0.7411,1.63916 0.386,1.57396 0.05,1.06242 c -0.0804,114.31284 -0.10418,228.63693 -0.0983,342.96694 0.008,155.52282 0.0712,311.05662 0.12178,466.58792 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path400" d="m 280.0489,334.04973 -2.8746,2.16498 -1.3945,1.27122 -1.1064,1.18868 -1.3392,1.49729 -1.3821,1.73597 -1.1375,1.54737 -1.1471,1.61493 -1.7633,2.77824 -1.1335,1.98857 -0.9191,1.69028 -1.3324,2.59146 -1.1121,2.32402 -1.5658,3.3824 -0.6357,1.21716 -0.7728,1.8524 -0.7249,1.7502 -0.989,2.11092 -1.0447,2.26153 -0.86,1.70122 -0.7487,1.45807 -0.7784,1.50072 -1.1616,2.03112 -0.6994,1.16648 -1.3216,2.11047 -1.1613,1.58472 -0.9183,1.1248 -1.4672,1.69512 -1.42,1.41779 -1.9934,1.72491 -2.2557,1.72298 -2.1512,1.20455 -1.3718,0.68514 -3.115,1.23076 -4.1538,1.06111 -3.0868,0.4675 -3.2213,0.30214 h -28.4829 l -0.9465,0.0522 -0.9784,0.35707 -1.1635,0.4739 -0.9822,0.69974 -1.0146,1.07545 -0.9282,1.35489 -0.6502,1.7225 -0.1277,1.59156 0.296,1.44131 0.7415,1.59064 1.9905,3.44769 2.4225,4.15209 2.3354,3.53006 1.3741,1.96135 1.2426,1.70362 1.4133,1.82618 1.3411,1.74059 2.1466,2.65906 1.9723,2.30436 1.0859,1.37163 2.4142,2.76344 1.3089,1.52486 3.0336,3.39354 1.5816,1.80314 1.3444,1.31094 2.4631,2.62274 1.0462,1.088 4.8462,5.01965 3.6011,3.76598 1.7432,1.82423 2.1054,2.24013 6.0616,6.47629 2.3937,2.58723 2.014,2.19763 1.6282,1.85126 1.1405,1.25224 1.6465,1.98007 1.726,2.18054 1.5288,1.91466 1.2553,1.47803 1.1294,1.5201 1.6519,2.24592 1.1514,1.59813 1.313,1.80747 1.0891,1.73386 1.8619,2.95681 1.9716,3.31485 1.215,2.46611 1.3695,2.68245 0.9533,2.4215 1.0707,2.90707 0.7627,2.01532 h 0.6246"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path402" d="m 419.6848,525.27774 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5718 -0.1723 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path404" d="m 419.7599,446.71674 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4608,1.28829 0.064,0.91052 0.158,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.07,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3264,4.36272 -0.1217,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5717 -0.1724 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path406" d="m 419.3182,991.21629 0.7067,0.005 1.1504,0.26365 0.9444,0.76195 0.3328,0.70813 v 46.67098 l -0.351,0.8325 -1.1666,0.8966 -0.7662,0.1774 -0.7976,-0.036 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path408" d="m 292.23542,321.94382 -2.85482,0.19193 -3.5205,0.79532 -3.2999,0.79136 -3.3568,0.85492 -10.5848,3.04972 -8.2427,2.61122 -6.9829,2.30208 -8.1913,2.71333 -6.855,2.11775 -7.5618,2.21755 -3.0235,0.89028 -3.0148,0.78091 -2.5919,0.65281 -4.3968,1.00847 -3.4498,0.73028 -4.1489,0.73001 -5.6739,0.74708 -2.2602,0.25755 -2.5162,0.19354 -1.5131,0.53719 -1.7144,0.82362 -1.1537,0.80424 -0.8192,0.61627 -1.0935,1.16923 -1.2892,1.65867 -1.0363,2.0311 -0.4006,1.59894 -0.1889,1.03517 v 22.38615 l 0.1909,1.30564 0.4958,1.40886 0.8296,1.64975 0.8332,1.21754 1.2656,1.51781 1.473,1.67519 1.7472,1.806 1.5258,1.66687 1.0269,1.42626 0.5157,0.92256"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path410" d="m 419.5504,789.12692 1.0104,0.39157 1.2284,0.93414 1.2742,1.0266 1.3335,1.34755 1.3498,1.58941 1.4074,1.79596 1.068,1.4886 0.8509,1.19973 0.8928,1.39146 0.9973,1.62576 0.6021,1.24333 0.8025,1.68804 0.9324,1.96316 0.9148,2.22486 0.6262,1.90738 0.5734,2.0049 0.5948,2.79681 0.1489,0.35893 1.1814,-0.13758 0.9744,-0.18453 1.2915,-0.53944 1.0017,-0.68907 1.1544,-0.99535 0.604,-0.85004 0.4934,-1.12029 0.3702,-1.37331 v -45.33419 l 0.2034,-1.17653 0.748,-1.09495 0.8786,-0.84648 1.1084,-0.65922 1.6277,-0.61299 1.9995,-0.31181 2.419,-0.0432 3.3419,0.50976 2.789,1.02605 1.7576,0.92574 1.4806,0.99459 2.1054,1.92583 1.357,1.78977 0.7746,1.80358 0.5382,2.14337 0.1755,1.82459 v 15.36545 l 0.7426,2.32837 0.8151,3.04194 0.6637,2.10231 1.4461,5.39684 0.1081,0.54415 0.3624,1.61807 0.4384,2.00735 0.5281,2.58998 0.5111,2.93668 0.532,3.40847 0.5218,3.68177 0.2738,2.55863 0.1742,1.97306 0.125,1.76412 0.1687,2.52444 0.093,2.5116 0.1008,2.95717 0.032,3.58916 -0.1372,3.61839 -0.1588,3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path412" d="m 419.5504,878.18361 1.0104,-0.39157 1.2284,-0.93414 1.2742,-1.0266 1.3335,-1.34755 1.3498,-1.58941 1.4074,-1.79596 1.068,-1.4886 0.8509,-1.19973 0.8928,-1.39146 0.9973,-1.62576 0.6021,-1.24333 0.8025,-1.68804 0.9324,-1.96316 0.9148,-2.22486 0.6262,-1.90738 0.5734,-2.0049 0.5948,-2.79681 0.1489,-0.35893 1.1814,0.13758 0.9744,0.18453 1.2915,0.53944 1.0017,0.68907 1.1544,0.99535 0.604,0.85004 0.4934,1.12029 0.3702,1.37331 v 45.33419 l 0.2034,1.17653 0.748,1.09495 0.8786,0.84648 1.1084,0.65922 1.6277,0.61299 1.9995,0.31181 2.419,0.0432 3.3419,-0.50976 2.789,-1.02605 1.7576,-0.92574 1.4806,-0.99459 2.1054,-1.92583 1.357,-1.78977 0.7746,-1.80358 0.5382,-2.14337 0.1755,-1.82459 v -15.36545 l 0.7426,-2.32837 0.8151,-3.04194 0.6637,-2.10231 1.4461,-5.39684 0.1081,-0.54415 0.3624,-1.61807 0.4384,-2.00735 0.5281,-2.58998 0.5111,-2.93668 0.532,-3.40847 0.5218,-3.68177 0.2738,-2.55863 0.1742,-1.97306 0.125,-1.76412 0.1687,-2.52444 0.093,-2.5116 0.1008,-2.95717 0.032,-3.58916 -0.1372,-3.61839 -0.1588,-3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path414" d="m 345.6694,529.78706 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 -1.2064,0.95657 -1.075,1.06404 -1.1014,1.41493 -0.594,1.14722 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69762 l 0.1365,1.11638 0.2065,0.99097 0.3274,0.9147 0.2958,0.88818 0.5023,0.98607 0.7034,1.07023 0.7271,0.83072 1.1425,1.22917 0.9548,0.84847 1.1231,0.73807 1.3029,0.76185 1.5781,0.61856 1.753,0.41994 1.6248,0.25206 1.9291,0.0355 12.21761,-0.15231 1.24069,0.009 1.4416,-0.26481 1.209,-0.3538 1.3406,-0.58952 1.2548,-0.64457 0.9072,-0.5388 1.0383,-0.81994 0.7108,-0.73783 0.6713,-0.63536 1.2672,-1.78476 1.0821,-2.39096 0.4226,-1.73078 0.032,-1.77014 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path416" d="m 345.6694,929.08474 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 c -0.40213,0.31886 -0.80427,-0.0101 -1.2064,0.95657 -1.1612,-0.13384 -0.80827,0.40421 -1.2124,0.60632 l -1.03457,1.59803 -0.52343,1.42184 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69758 l 0.1365,1.1164 0.2065,0.991 0.3274,0.9147 0.2958,0.8882 0.5023,0.986 0.7034,1.0703 0.7271,0.8307 1.1425,1.2292 0.9548,0.8484 1.1231,0.7381 1.3029,0.7618 1.5781,0.6186 0.84467,0.2023 0.90833,0.2176 1.6248,0.2521 1.9291,0.035 h 12.2138 l 1.2445,-0.1435 1.4416,-0.2648 1.209,-0.3538 1.3406,-0.5895 1.2548,-0.6446 0.9072,-0.5388 1.0383,-0.8199 0.7108,-0.7378 0.6713,-0.6354 1.2672,-1.7847 1.0821,-2.391 0.4226,-1.7308 0.032,-1.77012 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path426" d="m 269.3709,404.13671 h -4.9495 l -1.0113,0.19773 -1.022,0.65678 -0.7694,0.84217 -0.623,1.27551 -0.4117,1.3715 -0.6037,2.17152 -0.5303,2.14305 -0.3827,1.9667 -0.3142,1.95063 -0.2528,2.01116 -0.2212,2.18086 -0.1418,2.35493 -0.046,2.05813 0.034,2.89349 0.1866,2.92296 0.2597,3.11808 0.3257,2.74124 0.4726,2.4298 0.3837,2.06422 0.6228,2.42502 0.4876,1.70136 0.5673,1.13322 0.656,0.75539 0.7893,0.54624 0.78,0.31802 0.8271,0.091 h 5.1673 0.2296 v -44.33098 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path428" d="m 419.3062,396.58247 h 3.3623 l 0.9525,0.25724 0.8868,0.75004 0.3797,1.09319 v 10.77754 l -0.3997,0.99826 -0.4739,0.71234 -0.6363,0.44149 -0.5074,0.1596 h -3.3662 -0.2116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path430" d="m 368.2112,1052.977 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path432" d="m 368.2112,1097.1347 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path434" d="m 368.2112,1141.3197 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path436" d="m 343.5847,1042.2128 h -27.013 l -1.8698,0.2799 -1.342,0.3586 -1.606,0.6627 -1.1661,0.7504 -1.1412,0.8758 -0.7833,0.8235 -0.7034,0.7948 -0.6319,1.1103 -0.4797,0.9867 -0.3453,1.0256 -0.2487,1.1948 -0.069,0.83 v 125.1345 l 0.052,0.8702 0.1667,1.0482 0.4222,1.1949 0.7328,1.4918 0.8537,1.1485 1.4176,1.3519 1.1779,0.9169 1.5965,0.8574 1.9127,0.6145 1.7443,0.195 h 57.292 l 1.482,-0.1169 1.5379,-0.379 1.0258,-0.4189 1.0471,-0.555 0.7983,-0.4851 1.0868,-0.8153 1.1798,-1.2764 0.6871,-0.9185 0.4367,-0.7747 0.3972,-0.7651 0.3643,-1.035 0.1713,-0.7948 0.086,-1.2186 v -125.1426 l -0.076,-1.0984 -0.204,-0.9502 -0.2266,-0.7979 -0.3429,-0.7631 -0.7969,-1.4695 -0.8643,-1.1417 -1.3636,-1.2219 -1.4025,-0.9472 -0.7682,-0.4017 -1.6691,-0.5921 -1.312,-0.2496 -1.4844,-0.1821 -1.158,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path438" d="m 390.4523,307.66577 v -3.14841 l -0.3715,-1.45506 -0.7559,-1.06735 -1.1876,-0.97885 -1.7025,-0.48365 h -45.228 l -1.5835,0.18859 -1.2132,0.58802 -0.8602,0.6336 -0.6208,0.61481 -0.7767,1.21911 -0.2726,1.3989 v 2.48519 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path440" d="m 419.68509,599.75674 h 3.3148 l 1.2108,0.19587 1.41971,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.28051,0.22452 h -4.5718 -0.1723 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path506" d="m 420.36151,634.93249 v -34.75633 l 2.0263,0.23815 c 2.75467,0.32376 4.80203,1.57598 5.69709,3.48449 1.06072,2.26176 1.52361,9.71023 1.72256,27.71794 0.14637,13.24854 0.0672,17.02245 -0.52828,25.19166 -0.77583,10.64303 -0.85918,10.95183 -3.29112,12.19251 -0.89452,0.45635 -2.06849,0.68792 -3.48749,0.68792 h -2.13906 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path508" d="m 420.36151,560.56402 v -34.75143 l 1.85933,0.15785 c 2.39951,0.20371 4.31925,1.13642 5.48512,2.66497 0.83656,1.09678 0.97668,1.7388 1.39976,6.41356 0.25858,2.85712 0.56214,12.52586 0.67458,21.48608 0.1781,14.19187 0.11309,17.54027 -0.50447,25.983 l -0.70891,9.69168 -1.16519,1.20216 c -1.30344,1.34481 -2.86398,1.89866 -5.35797,1.90159 l -1.68225,0.002 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path510" d="m 420.36151,481.93505 v -34.75712 l 1.92371,0.19854 c 2.49155,0.25715 4.263,1.11778 5.41822,2.63234 1.41345,1.85314 1.85463,7.51526 2.10513,27.01756 0.17647,13.73942 0.10561,18.07268 -0.42766,26.14973 -0.46732,7.07821 -0.78975,9.98262 -1.19916,10.80185 -0.79619,1.59315 -3.17954,2.71422 -5.77033,2.71422 h -2.04991 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path512" d="m 447.5015,906.00098 c -1.8715,-0.70661 -2.9819,-1.7154 -3.3712,-3.06268 -0.2644,-0.9154 -0.3472,-22.05223 -0.2745,-70.13291 l 0.1041,-68.8226 1.2946,-1.18645 c 2.041,-1.87038 4.9744,-2.37787 9.1933,-1.59049 4.2243,0.78838 8.8238,4.07342 10.363,7.40147 0.6902,1.49247 0.7677,2.40752 0.9325,11.01292 l 0.1796,9.38522 1.7041,5.81417 c 7.6872,26.22849 7.7031,50.97284 0.05,77.62707 l -1.8918,6.58875 -0.1107,9.17132 -0.1107,9.17132 -1.0625,1.92041 c -1.2599,2.27718 -3.7071,4.33173 -6.8926,5.78647 -1.902,0.86861 -2.8591,1.06811 -5.6666,1.18115 -2.0013,0.0806 -3.8109,-0.0275 -4.4404,-0.26514 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path514" d="m 441.6385,852.73071 c -0.5999,-0.72278 -2.3597,-1.63125 -3.6993,-1.9097 l -1.06248,-0.22083 -0.092,-16.88205 -0.092,-16.88205 1.50858,-0.39612 c 0.8297,-0.21787 2.1062,-0.86942 2.8367,-1.4479 l 1.3281,-1.05178 v 19.67251 c 0,10.81988 -0.06,19.67251 -0.1337,19.67251 -0.074,0 -0.3409,-0.24956 -0.594,-0.55459 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path516" d="m 420.05417,833.61702 v -43.39693 l 0.79594,0.42597 c 0.43776,0.23429 1.60747,1.27059 2.59935,2.30289 4.51391,4.69789 9.10684,12.69355 10.93014,19.02792 l 0.9034,3.1385 v 18.51411 18.51411 l -0.90522,3.13851 c -1.92215,6.6643 -6.56913,14.65718 -11.23693,19.32767 -1.32154,1.3223 -2.55667,2.40418 -2.74474,2.40418 -0.21796,0 -0.34194,-15.73501 -0.34194,-43.39693 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path524" d="m 313.99198,1292.8085 c -0.96622,-0.2545 -2.10487,-0.9559 -3.09247,-1.3094 -1.70548,-0.6104 -3.38805,-1.3678 -5.04339,-2.0839 -13.35521,-5.7781 -24.71137,-15.7518 -30.37881,-29.3689 l -5.07081,-12.1835 0.21567,-447.85593 -1.68502,-452.83955 5.21819,-6.82435 c 6.70736,-8.77188 19.17143,-19.4178 30.32839,-25.75165 12.83574,-7.28691 20.41017,-6.77706 55.40112,-6.27587 29.89918,0.42825 32.28987,-0.2527 38.18687,2.89292 7.63586,4.07316 15.0438,13.06457 18.54681,20.55351 0.66444,1.42047 1.68556,3.4563 2.05056,13.27608 1.04826,28.20251 0.44492,121.62908 -0.18564,457.03992 l -0.066,459.79922 -0.81036,6.3982 -3.45262,8.1963 c -1.76025,4.1787 -8.98897,10.0118 -12.10386,12.1705 -10.15801,7.0395 -14.51748,6.4392 -48.74484,6.3559 -20.03132,-0.049 -28.55486,0.083 -34.44933,-1.0022 -1.84725,-0.34 1.41291,0.4661 -0.16387,0.051 z m 78.87474,-99.2762 3.27873,-3.0802 v -65.5066 l -0.2424,-215.7738 0.25427,-68.97059 0.0331,-61.49435 c 0.11334,-210.56388 -0.50479,-313.30624 -0.8914,-364.08471 -0.35613,-46.77635 -0.40721,-49.50115 -1.95288,-50.80192 l -2.99002,-2.51629 -44.14324,-1.50348 -43.58958,0.51399 -4.70273,2.60905 -3.53443,3.53443 v 412.25021 412.25016 l 2.86193,2.7659 c 2.93271,2.8342 4.77438,2.8884 47.72015,2.8884 43.86243,0 44.67543,-0.052 47.8985,-3.0802 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path526" d="m 264.23721,492.50948 c -4.04844,-8.33293 -16.624,-23.7182 -35.08385,-43.12156 -26.81029,-28.1806 -38.94038,-44.27168 -38.0073,-50.84946 0.2392,-1.68623 1.46532,-4.24344 5.12049,-5.01886 3.19131,-0.67702 8.11058,0.35187 17.45091,-0.0198 23.39935,-0.93118 25.92443,-0.22204 34.18969,-9.37069 2.82569,-3.12771 9.72884,-13.68396 13.55981,-21.88811 2.0257,-4.33811 4.05045,-8.45316 5.51052,-10.90389 0.76226,-1.27947 1.07024,-2.31363 1.47031,-2.76411 0.28284,-0.31849 0.76027,-0.22269 0.8214,-0.25623 1.85097,-1.01578 0.12781,12.83353 -0.1142,27.83216 l 0.24214,24.66349 -0.68216,2.60676 h -3.52801 c -5.21935,0 -7.63511,7.05409 -7.62545,22.26651 0.0108,17.00318 1.77689,22.92697 7.15611,24.00281 l 4.16908,0.83382 v 23.90572 c 0,13.14815 0.49174,29.00863 0.25743,29.00863 -0.23432,0 -3.28323,-7.58512 -4.90692,-10.92716 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path528" d="m 295.1401,1185.4149 c -3.06937,-3.2672 5.67849,-7.7931 8.85227,-71.9607 l 3.14349,-63.5553 0.59066,-4.8296 c 0.52648,-4.3049 8.30627,-3.402 38.30164,-3.402 25.86749,0 38.24755,-2.2189 38.03519,0.9698 l 3.45868,11.3714 -2.79167,59.5757 3.06297,66.1632 -6.74309,5.9725 c -2.39371,2.1201 -8.12035,2.5912 -34.16751,2.5912 -30.89856,0 -48.7031,0.3392 -51.74263,-2.8962 z m 60.60873,-26.4444 c 6.3449,-10.045 11.38379,-15.7341 11.38379,-16.2306 0,-0.4966 -8.67254,-0.2057 -22.30766,-0.2057 -13.63512,0 -20.98513,-0.1734 -20.98513,0.1875 0,1.9194 20.33259,34.7155 21.23584,34.1572 0.58838,-0.3636 4.32826,-7.8634 10.67316,-17.9084 z m 1.57196,-45.1746 c 6.02548,-9.6095 10.68997,-15.7918 10.34635,-16.1355 -0.34362,-0.3436 -10.16328,-1.4002 -23.54772,-1.1865 l -22.58982,0.6608 12.33804,18.1627 c 12.12402,17.8476 11.33234,16.5866 12.68919,15.1005 0.93353,-1.0226 4.73849,-6.9926 10.76396,-16.602 z m -4.74836,-38.5533 c 6.72239,-10.6062 12.20345,-20.4597 11.88264,-20.7805 -0.32082,-0.3208 -6.79848,0.016 -20.13412,-0.1191 l -20.97842,-0.2121 10.503,17.5628 c 6.49171,10.8554 11.17262,15.0769 11.09751,17.0875 -0.008,0.2094 0.90699,-2.9325 7.62939,-13.5386 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path530" d="m 195.38552,386.2328 c -4.58371,-5.30681 -4.27509,-6.14052 -4.27509,-19.98524 0,-17.24523 1.72279,-19.61607 15.05755,-21.23724 9.67784,-1.17658 22.06465,-2.66101 54.5917,-14.7228 13.93049,-5.16576 29.54685,-8.05337 29.95931,-7.6409 0.41247,0.41246 -7.82477,7.64243 -12.70328,12.40148 -7.11384,6.93963 -10.0361,11.45679 -15.83597,23.5081 -9.7373,20.23271 -12.31671,25.43301 -19.9502,29.92064 -5.8988,3.46784 -9.64568,4.83664 -24.46127,4.50485 l -16.87996,-0.37801 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path532" d="m 260.25826,445.73518 c -0.87612,-2.14266 -2.24387,-11.42662 -2.30953,-18.43896 -0.0789,-8.42481 0.5889,-15.94359 2.95394,-19.86196 1.46407,-2.42565 4.20484,-2.8223 5.93526,-3.15555 0.81862,-0.15765 2.20028,-0.94768 2.77122,0.7176 1.00427,2.92917 0.90932,10.69905 0.90932,23.15575 0,20.49599 0.29677,21.57233 -2.45639,21.57233 -1.7985,0 -6.80502,-1.5465 -7.80382,-3.98921 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path534" d="m 335.78812,307.06698 c 0,-1.77848 0.75861,-5.19179 4.31531,-6.11265 4.01911,-1.04059 12.44741,0.017 24.70426,0.21676 11.74082,0.19135 18.48536,-0.47698 21.97918,0.38297 2.88441,0.70995 3.12648,3.58747 3.31976,4.59386 0.43963,2.28916 -2.61413,0.94 -26.90979,0.94 -14.47139,0 -27.40872,0.6628 -27.40872,-0.0209 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path536" d="m 424.74041,404.13845 c 8.8e-4,-3.58112 0.0807,-4.98041 0.17728,-3.10952 0.0966,1.87089 0.0959,4.8009 -0.002,6.51113 -0.0975,1.71024 -0.17656,0.17952 -0.17569,-3.40161 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path538" d="m 420.0381,404.10822 v -6.7918 l 1.87821,0.15545 1.87822,0.15545 0.14568,5.50942 c 0.1916,7.24582 0.0477,7.76327 -2.15865,7.76327 h -1.74346 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path548" d="m 334.02423,1070.9922 -10.6817,-16.8613 10.97722,-0.1953 c 6.03746,-0.1074 15.72027,-0.1074 21.51734,0 l 10.54013,0.1953 -10.29748,16.2913 c -5.66361,8.9602 -10.53965,16.5478 -10.83564,16.8613 -0.296,0.3136 -5.34494,-7.0175 -11.21987,-16.2913 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path550" d="m 334.02948,1115.1625 -10.82491,-17.1159 11.04619,-0.1953 c 6.07541,-0.1074 15.82454,-0.1074 21.66473,0 l 10.61853,0.1953 -10.74364,16.9996 c -5.90901,9.3498 -10.78693,17.052 -10.83982,17.1159 -0.0529,0.064 -4.96738,-7.5858 -10.92108,-16.9996 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path552" d="m 334.13106,1159.4901 -10.61146,-16.8195 10.88868,-0.1953 c 5.98878,-0.1074 15.60026,-0.1074 21.35885,0 l 10.47016,0.1953 -10.39596,16.468 c -5.71779,9.0575 -10.55411,16.6262 -10.74739,16.8195 -0.19329,0.1933 -5.12658,-7.2173 -10.96288,-16.468 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path572" d="m 420.0231,1016.5918 c 0,-20.55693 0.0782,-24.48013 0.48787,-24.48013 1.26302,0 1.28964,0.54348 1.19693,24.43313 l -0.0911,23.4691 -0.79685,0.529 -0.79686,0.5291 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#1a1a1a;stroke-width:.25;stroke-opacity:1" id="path987" d="m 336.33885,1011.7736 c -0.4903,-0.1025 -1.34011,-0.499 -1.86387,-0.5891 -2.10906,-0.3631 -4.24247,-1.0485 -6.03886,-2.8281 -2.21068,-2.1901 -2.45772,-4.2576 -2.92495,-7.2201 -0.0644,-0.4083 -0.33547,-3.32902 -0.7219,-7.96551 -0.47191,-5.66195 -0.26588,-14.13412 -0.22086,-24.07743 l 0.13273,-29.31033 2.1854,-3.07209 c 1.68451,-2.36796 2.85286,-4.8002 5.70807,-6.16483 3.14456,-1.50292 4.3061,-1.05628 13.1741,-0.94462 7.32026,0.0922 8.2212,0.0618 9.5738,0.56462 4.38444,1.62985 7.57683,5.059 8.6811,9.18385 0.22909,0.85573 0.41962,8.86488 0.21397,32.35897 l -0.056,30.50887 -0.83085,2.4841 c -0.94256,2.8179 -3.22521,4.2492 -5.91157,5.5336 -1.13944,0.5447 -2.59573,1.1447 -3.33637,1.2835 -1.10922,0.2079 -5.88727,0.4361 -10.04355,0.3913 -2.3498,-0.025 -3.61164,0.2383 -5.14351,0.029 -0.87269,-0.1194 -0.99665,0.165 -1.3228,0.097 z m 13.30469,-23.7451 c 2.76719,-0.58714 4.69699,-2.04661 5.74377,-4.34391 0.47551,-1.04356 0.57052,-1.68351 0.57531,-3.875 0.009,-4.20728 -1.02802,-6.30701 -3.78078,-7.65381 -2.39779,-1.17313 -5.79519,-0.86226 -7.69553,0.70416 -1.16483,0.96015 -1.85705,2.35288 -3.009,6.05403 -1.00853,3.24035 -1.41582,4.0427 -2.17437,4.28345 -1.5805,0.50163 -2.90029,-1.36574 -2.62256,-3.71068 0.19465,-1.64357 0.66036,-2.28932 2.02759,-2.81147 1.12124,-0.4282 1.13535,-0.44797 1.13263,-1.58714 -0.002,-0.63445 -0.0725,-1.57541 -0.15771,-2.09104 -0.13433,-0.81269 -0.24453,-0.9375 -0.82772,-0.9375 -2.30578,0 -4.85058,1.92056 -5.66126,4.27257 -0.69366,2.01248 -0.63686,5.68454 0.11372,7.35243 1.14973,2.55483 2.92227,3.72494 5.66589,3.74023 1.40395,0.008 2.00379,-0.11802 2.99769,-0.62888 1.9043,-0.97879 2.69476,-2.2324 3.99147,-6.3301 1.20414,-3.80517 1.74731,-4.65625 2.9717,-4.65625 0.97546,0 2.09342,0.64567 2.49633,1.44174 1.35565,2.67848 0.17187,5.70204 -2.55195,6.51812 -0.93521,0.2802 -1.0352,0.38787 -1.03324,1.11268 0.003,0.96835 0.28627,3.42746 0.39535,3.42746 0.0428,0 0.67403,-0.12649 1.40267,-0.28109 z m 5.94981,-29.21891 v -7.5 h -2 -2 v 5.25 5.25 h -9.25 -9.25 v 2.25 2.25 h 11.25 11.25 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path504" d="m 300.85,1194.9934 c -1.71731,-0.8472 -4.91972,-2.1462 -5.54391,-3.5161 -0.83944,-1.8424 0.86542,-110.6107 0.86542,-412.9166 0,-355.43486 -2.26943,-409.5887 -1.00378,-412.03621 2.62275,-5.07184 6.80299,-6.80795 52.50153,-5.38304 l 40.5665,0.52575 3.70004,2.69699 2.40356,3.70288 v 409.59752 c 0,267.41961 0.6532,377.35501 0.22653,405.85801 -0.0462,3.0834 0.15924,4.3842 0.0303,5.658 -0.0851,0.8402 -0.5067,2.1372 -0.56245,2.2596 -2.45684,5.3924 -4.14164,3.9318 -48.47815,3.9071 -34.72063,-0.019 -42.05298,0.9547 -44.70561,-0.3539 z m 80.27252,-10.4604 c 2.12921,-1.989 3.21222,-4.1353 3.6646,-7.2624 0.35319,-2.4415 0.50577,-32.4911 0.33906,-66.777 l -0.30309,-62.3379 -1.817,-4.7667 -4.72991,-1.7818 -30.78478,-0.3127 c -34.35748,-0.3489 -37.22985,0.016 -40.34521,5.1254 -1.88189,3.0863 -1.95191,5.545 -1.95552,68.6629 l -0.004,65.4619 3.40582,3.4058 3.40582,3.4059 h 33.05076 33.05075 z m -22.91983,-173.0609 c 1.57682,-0.8154 3.84958,-2.6835 5.00011,-4.1461 2.02772,-2.5779 2.08689,-3.5907 2.08689,-36.43981 l -0.69949,-33.99855 -2.38805,-3.40626 c -3.72994,-4.24816 -8.21239,-5.25265 -18.24178,-5.26006 -5.84642,-0.004 -8.30481,0.20024 -11.76537,1.9453 -7.84443,3.95572 -7.97242,4.60298 -7.97242,40.31894 0,34.66614 0.41247,35.72854 7.12185,40.21074 2.99392,2.0001 4.44288,2.362 13.60803,2.362 7.24014,0 11.25811,-0.556 13.25023,-1.5862 z m -5.95573,-138.90396 c 6.10086,-3.11739 8.53502,-6.75988 8.53502,-12.77184 0,-8.4223 -5.95352,-14.17655 -15.26265,-14.7518 -7.02351,-0.43401 -12.57208,2.34255 -15.43573,7.72419 -7.14597,13.42935 8.05461,27.00867 22.16336,19.79945 z m 1.45148,-63.42988 c 1.10087,-1.10086 1.57412,-3.48865 1.57412,-7.94215 0,-8.51585 -1.07862,-9.51627 -10.26023,-9.51627 -9.38389,0 -10.77573,1.20668 -10.77573,9.34222 0,8.48897 1.31434,9.69032 10.60168,9.69032 5.28806,0 7.7177,-0.43166 8.86016,-1.57412 z m 0.37207,-38.69473 c 0.69725,-0.69725 1.20205,-4.03875 1.20205,-7.9569 0,-8.44376 -1.52314,-9.87359 -10.51798,-9.87359 -8.88853,0 -10.51798,1.47199 -10.51798,9.50153 0,8.65087 1.00564,9.53101 10.89005,9.53101 4.68578,0 8.21631,-0.4745 8.94386,-1.20205 z m -0.62982,-39.52257 c 2.44013,-2.20828 2.62327,-13.43508 0.25775,-15.80059 -2.26592,-2.26593 -15.101,-2.20499 -17.62997,0.0837 -2.48085,2.24514 -2.59975,12.86248 -0.17405,15.54285 2.27669,2.51572 14.82125,2.64015 17.54627,0.17404 z m -0.1057,-38.44592 c 1.6168,-0.86529 1.93757,-2.13749 1.93757,-7.6844 0,-9.02878 -1.23743,-10.31119 -9.94949,-10.31119 -9.51513,0 -11.08647,1.3467 -11.08647,9.50153 0,8.51102 1.08671,9.53101 10.15453,9.53101 3.85346,0 7.8782,-0.46663 8.94386,-1.03695 z m 4.89747,-81.8069 c 5.473,-3.60783 6.98335,-3.06909 7.02174,-39.48044 0.0344,-32.65824 -0.45612,-33.68452 -2.485,-36.2638 -1.3225,-1.68128 -2.16617,-2.68325 -3.79664,-3.53269 -2.85079,-1.4852 -6.79655,-1.97333 -14.0201,-1.97333 -9.16515,0 -9.82283,0.81199 -12.81675,2.81203 -6.85365,4.57854 -7.27471,4.72625 -6.9653,40.5757 0.2612,30.26439 -0.11042,32.144 1.7811,34.65729 3.82743,5.08555 5.86745,5.85717 18.30393,5.87882 9.72787,0.0169 10.49635,-1.03831 12.97702,-2.67358 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.373293;stroke-opacity:1" id="path989" d="m 337.67662,692.88512 c -2.67305,-0.96309 -3.2939,-2.84605 -3.09019,-9.37193 0.17168,-5.49938 0.64108,-6.64523 3.20441,-7.82229 1.52187,-0.69884 2.42425,-0.79766 7.30307,-0.79982 6.75767,-0.003 7.98061,0.38279 9.09592,2.86921 0.61253,1.3655 0.72342,2.47625 0.73034,7.31525 0.007,5.38513 -0.0388,5.75973 -0.82685,6.67489 -0.62002,0.71994 -1.40826,1.06314 -3.06165,1.33297 -3.40014,0.55493 -11.60256,0.43314 -13.35505,-0.19828 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370491;stroke-opacity:1" id="path991" d="m 339.04414,731.97109 c -3.60561,-0.93726 -4.48264,-2.73045 -4.45483,-9.10842 0.0218,-5.00727 0.73904,-7.15345 2.73101,-8.17253 1.29271,-0.66135 2.19762,-0.74953 7.69168,-0.74953 8.49855,0 8.96303,0.26628 9.77396,5.60339 0.32491,2.13833 0.32915,3.61396 0.0172,5.9992 -0.53103,4.06091 -1.10757,5.18233 -3.09269,6.01548 -2.09206,0.87802 -9.89752,1.13216 -12.66637,0.41241 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.365528;stroke-opacity:1" id="path993" d="m 337.75825,770.7391 c -2.54567,-0.94315 -3.11216,-2.48804 -3.09149,-8.43076 0.028,-8.05586 1.30547,-9.15871 10.57454,-9.12914 4.14079,0.0132 5.1614,0.13044 6.36851,0.73158 2.63337,1.31141 2.92902,2.08079 3.06977,7.98827 0.13827,5.8041 -0.24296,8.00904 -1.50624,8.71158 -1.28401,0.71409 -13.55834,0.81639 -15.41509,0.12847 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370789;stroke-opacity:1" id="path995" d="m 340.25178,810.31175 c -2.30728,-0.35082 -4.07035,-1.26307 -4.79602,-2.48153 -0.63065,-1.05893 -0.72313,-1.90705 -0.72313,-6.63222 0,-8.75452 0.4422,-9.15459 10.11842,-9.15459 9.55452,0 9.93447,0.34222 9.93447,8.94819 0,8.55026 -0.56098,9.15949 -8.62352,9.3653 -2.64352,0.0675 -5.30312,0.0472 -5.91022,-0.0451 z"/><path id="path4136" d="m 620.05176,101.33936 h -13.19009 l -0.0372,-8.25531 h -14.10678 c -3.694,0 -4.86707,3.29254 -4.86707,8.2606 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 606.85329,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 678.37103,56.29539 v 15.94604 h -43.5888 V 56.01064 c 0,-2.09826 1.87258,-3.04523 3.55963,-3.4883 12.17302,-3.19604 25.27663,-3.03408 36.83267,0 1.82189,0.47838 3.1965,1.67683 3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 720.40437,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 724.94622,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 741.03641,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 643.93309,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 746.85546,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 870.42561,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 797.67583,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 907.97933,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.47833 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.59359 -7.55529,-7.40352 -26.96999,-35.0496 -56.25473,-53.08707 -86.3059,-65.49263 h -63.63968 c -27.37307,12.02627 -42.63451,29.98675 -54.6313,49.5466 V 61.9055 c 0,4.46695 -3.77561,9.11203 -8.71777,9.11203 h -52.88777 v 128.70726 z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 898.96304,95.57843 H 671.57211 c 0.11854,-46.39485 23.40196,-94.42781 68.1792,-94.42781 l 63.60853,0.74648 c 62.27359,11.13309 75.07205,54.96226 95.6032,93.68133 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 917.62642,126.18349 H 669.66769 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 754.52313,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 763.60822,52.91602 V 42.51329 l 5.50031,0.0182 c 5.86555,0.0182 5.99551,0.0235 7.21251,0.23684 0.72764,0.12779 1.2063,0.27395 1.73262,0.5297 0.56119,0.27264 0.92919,0.53686 1.3444,0.96517 0.6865,0.70821 1.17119,1.61242 1.4232,2.65506 0.10465,0.43649 0.11392,0.54629 0.11623,1.4018 6.9e-4,0.72536 -0.0233,1.00826 -0.0743,1.29452 -0.49307,2.37268 -2.15713,3.86338 -4.92053,4.40866 -0.52052,0.10275 -0.58004,0.12279 -0.5089,0.17313 0.044,0.0312 0.27805,0.18384 0.51935,0.33899 1.26535,0.81414 2.04879,1.63119 3.24347,3.38328 0.43519,0.6382 3.38993,5.24266 3.43201,5.34806 0.0233,0.0423 -0.49075,0.051 -2.51118,0.0421 l -2.53257,-0.0114 -1.89628,-2.76629 c -2.70088,-3.93961 -3.00426,-4.35632 -3.57776,-4.91249 -0.79112,-0.76705 -1.35952,-0.94266 -3.17329,-0.98035 l -1.06565,-0.0228 v 4.3512 4.35117 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.66304 c 0.70021,-0.0758 1.02521,-0.15376 1.4046,-0.337 0.60955,-0.2945 1.03662,-0.84304 1.20307,-1.54567 0.0907,-0.37929 0.0884,-1.17286 -0.002,-1.51464 -0.27525,-1.03723 -1.09727,-1.6771 -2.30428,-1.79364 -0.22549,-0.0228 -1.74122,-0.0399 -3.36922,-0.0406 l -2.96011,-0.002 v 2.66306 2.66304 l 2.78783,-0.0228 c 1.66078,-0.0137 2.97079,-0.0419 3.23998,-0.0711 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 743.58665,61.4392 v -1.87954 l 5.57588,-6.74897 c 3.06678,-3.71194 5.57589,-6.75827 5.57589,-6.76966 0,-0.0114 -2.22827,-0.0205 -4.95147,-0.0205 h -4.95146 v -1.75092 -1.75094 h 7.7716 7.77183 v 1.61419 1.61418 l -5.83789,7.04557 -5.83763,7.04554 6.05291,0.0114 6.05316,0.0114 v 1.7297 1.72968 h -8.6113 -8.61152 v -1.87951 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path141" d="m 337.37689,564.16039 c 0.004,-3.45814 0.214,-4.28994 1.21089,-4.80544 1.18361,-0.61208 3.0461,-0.20122 3.8108,0.84064 0.33284,0.45348 0.37167,0.7949 0.42717,3.75651 l 0.0611,3.25769 h -2.7569 -2.7569 z"/></svg>
\ No newline at end of file
diff --git a/src/Ryujinx.Ui.Common/Resources/Controller_ProCon.svg b/src/Ryujinx.Ui.Common/Resources/Controller_ProCon.svg
deleted file mode 100644
index f5380f3a..00000000
--- a/src/Ryujinx.Ui.Common/Resources/Controller_ProCon.svg
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns:svg="http://www.w3.org/2000/svg"
-	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1050 1050.5"
-	 style="enable-background:new 0 0 1050 1050.5;" xml:space="preserve">
-<style type="text/css">
-	.st0{fill:#20221F;}
-	.st1{fill:#3B3B3B;}
-	.st2{fill:#121212;}
-	.st3{fill:#444542;}
-	.st4{fill:#FFFFFF;}
-	.st5{fill:#444542;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
-	.st6{fill:#454644;}
-	.st7{fill:#454644;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
-	.st8{fill:#3B3C3A;}
-	.st9{font-family:'Helvetica-Bold';}
-	.st10{font-size:40px;}
-	.st11{fill:#0D0D0A;}
-</style>
-<g id="Front">
-	<path id="Right_Grip_00000028282943321285403220000008369785803052272051_" class="st0" d="M766,850.5
-		c34,28.2,27.6,35.9,68.5,108.5c36.7,74.7,64.4,104.4,125.1,84.1v0c95.3-57.9,59.3-145.3,43.6-275.2c-10-60.6-35.6-190.3-35.6-190.3
-		L766,850.5z"/>
-	<path id="Left_Grip" class="st0" d="M82.3,577.6c0,0-25.6,129.7-35.6,190.3C31,897.8-5,985.1,90.3,1043v0
-		c60.8,20.3,88.4-9.4,125.1-84.1c40.9-72.7,34.5-80.3,68.5-108.5L82.3,577.6z"/>
-	<path id="Right_Bumper_00000006710349871522532470000011078040965381267594_" class="st1" d="M676.3,378.4
-		c10.1-4.3,39.7-22.5,58.7-19.7c59.5,0.9,166.7,17.7,172.6,81.2"/>
-	<path id="Left_Bumper_00000024680414077879639570000011759596763560342154_" class="st1" d="M142.4,439.9
-		c5.9-63.4,113-80.2,172.6-81.2c19-2.8,48.6,15.4,58.7,19.7"/>
-	<path id="Background_00000141418846164053065470000016150094984198570163_" class="st2" d="M766,850.5
-		c35.5-30.8,68.5-74.7,96-113.5c26.9-36.3,94.7-136.7,105.6-159.3c0-2.4-6.3-30.1-12.8-56.2C919.1,361.9,702.2,378.1,525,378.1
-		c-177.4,0-394.1-16.2-429.9,143.3c-6.5,26-12.8,53.8-12.8,56.2c10.9,22.6,78.8,123,105.6,159.3c27.5,38.8,60.5,82.8,96,113.5"/>
-	<g id="Directional_Pad">
-		<path id="Background_00000032628022449190479560000015279211462520783249_" class="st3" d="M466.2,683.5h-40c-2.8,0-5-2.2-5-5v-40
-			c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40
-			c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30C471.2,685.8,469,683.5,466.2,683.5z"/>
-		<g id="Arrows">
-			<g>
-				<polygon class="st4" points="393.7,746 408.7,746 401.2,761 				"/>
-			</g>
-			<g>
-				<polygon class="st4" points="358.7,696 358.7,711 343.7,703.5 				"/>
-			</g>
-			<g>
-				<polygon class="st4" points="408.7,661 393.7,661 401.2,646 				"/>
-			</g>
-			<g>
-				<polygon class="st4" points="443.7,711 443.7,696 458.7,703.5 				"/>
-			</g>
-		</g>
-	</g>
-	<g id="R_Thumbstick_00000152226188525111835500000011838297421350334865_">
-		<circle id="Background_00000035532849542660068350000006517224202948159422_" class="st0" cx="650.6" cy="703.5" r="55"/>
-		<circle id="Stick" class="st5" cx="650.6" cy="703.5" r="45"/>
-	</g>
-	<g id="L_Thumbstick_00000047032468231999382210000005512347386782594484_">
-		<circle id="Background_00000182502673988292164000000007125719133096369561_" class="st0" cx="240.2" cy="564.8" r="55"/>
-		<circle id="Stick_00000075121990265259598900000000214370239054002365_" class="st5" cx="240.2" cy="564.8" r="45"/>
-	</g>
-	<g id="Minus_Button">
-		<circle id="_Background_00000120554951013892796430000015877571645746699662_" class="st6" cx="401" cy="489.3" r="22.5"/>
-		<polyline id="Plus_00000039131319101621183460000006196023733899658629_" class="st4" points="386.2,491.8 386.2,486.8 
-			416.2,486.8 416.2,491.8 		"/>
-	</g>
-	<g id="Plus_Button">
-		<circle id="_Background" class="st6" cx="650.4" cy="489.6" r="22.5"/>
-		<polygon id="Plus" class="st4" points="665.6,487.1 653.1,487.1 653.1,474.4 648.1,474.4 648.1,487.1 635.6,487.1 635.6,492.1 
-			648.1,492.1 648.1,504.4 653.1,504.4 653.1,492.1 665.6,492.1 		"/>
-	</g>
-	<g id="Home_Button_00000029758737660217614780000001403165237001195407_">
-		<circle id="_Background_00000132788487854287834010000009548421243227981499_" class="st6" cx="605.4" cy="564.8" r="22.5"/>
-		<path id="Home" class="st4" d="M605.4,549.8l-15,15h5v15h20v-15h5L605.4,549.8z M610.4,574.8h-10v-10h10V574.8z"/>
-	</g>
-	<g id="Capture_Button_00000105394663133565750060000017455731898661404072_">
-		<path class="st6" d="M468.6,586.5h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5
-			C473.6,584.2,471.4,586.5,468.6,586.5z"/>
-		<circle class="st7" cx="453.6" cy="566.7" r="15"/>
-	</g>
-	<g id="Buttons_00000023239109225132251950000005218343074279628213_">
-		<g id="A_Button">
-			<circle id="Background_00000006699118933065716380000004636085088820886913_" class="st8" cx="863.9" cy="564.8" r="35"/>
-			<text transform="matrix(1 0 0 1 849.4224 578.6607)" class="st4 st9 st10">A</text>
-		</g>
-		<g id="X_Button">
-			<circle id="Background_00000083074713085756701790000016893839312974798515_" class="st8" cx="793.9" cy="494.8" r="35"/>
-			<text transform="matrix(1 0 0 1 780.5266 508.6604)" class="st4 st9 st10">X</text>
-		</g>
-		<g id="Y_Button_00000100344340438574137780000014238704828967683973_">
-			<circle id="Background_00000137100455694543496620000011124722786613194377_" class="st8" cx="723.9" cy="564.8" r="35"/>
-			<text transform="matrix(1 0 0 1 710.5263 578.661)" class="st4 st9 st10">Y</text>
-		</g>
-		<g id="B_Button_00000041994261956088037220000013468634544777304733_">
-			<circle id="Background_00000096038108578846046800000001873940014252420514_" class="st8" cx="793.9" cy="634.8" r="35"/>
-			<text transform="matrix(1 0 0 1 780.9706 648.6605)" class="st4 st9 st10">B</text>
-		</g>
-	</g>
-</g>
-<g id="Top_Down">
-	<path id="Left_Grip_00000026131988385328425370000016677941743356253314_" class="st0" d="M219.2,78.5
-		c-12.5-17.6-25.9-42.3-45.6-58.6C153.5,3.3,112.1-4.7,87.1,5.8c-13.9,5.8-33.4,33.1-42.7,52.8C33.9,80.9,30.4,109.9,32,141.4
-		c1.2,25.1,5.3,51.7,14.2,78.6c0,0,14.3,53.8,42.8,80.8c11.2,10.6,35,26.6,35,26.6l116-217.5C240,109.9,224.6,86.2,219.2,78.5z"/>
-	<path id="Right_Grip_00000016782759094708820330000002450847065936193693_" class="st0" d="M828.6,78.5
-		c12.5-17.6,25.9-42.3,45.6-58.6c20.1-16.6,61.4-24.5,86.5-14.1c13.9,5.8,33.4,33.1,42.7,52.8c10.5,22.3,13.9,51.3,12.4,82.8
-		c-1.2,25.1-5.3,51.7-14.2,78.6c0,0-14.3,53.8-42.8,80.8c-11.2,10.6-35,26.6-35,26.6l-116-217.5C807.8,109.9,823.2,86.2,828.6,78.5z
-		"/>
-	<path id="Background_00000169534857628063347190000007586592143875928969_" class="st11" d="M866,122.2
-		c66.3,18.7,85.1,128.8,69,186c-2.5,54.2-148.9,15.3-265.1,31.2c-41.1,1.7-91.8,2.4-145.9,2.3c-54.1,0-104.8-0.6-145.9-2.3
-		c-116.2-15.9-262.6,23.1-265.1-31.2c-16.1-57.1,2.6-167.3,69-186l60.5-18.8l38.9-1.9c40.2,0.1,142.8,0,242.7,0
-		c99.9,0,202.4,0.1,242.7,0l38.9,1.9L866,122.2z"/>
-	<g id="ZL_Trigger_00000005254517714433203260000014117442438696169895_">
-		<path id="Background_00000111870097528015387240000017384507710402295183_" class="st1" d="M145.9,239.2
-			c15.2-97.4,38.1-147.2,141.7-137c8.2,16.4,43.3,83,50.6,105.7C280.6,227.2,204.7,225.6,145.9,239.2z"/>
-		<text id="ZL_Trigger" transform="matrix(1.0139 0 0 1 218.3906 179.3992)" class="st4 st9 st10">ZL</text>
-	</g>
-	<g id="ZR_Trigger">
-		<path id="Background_00000133526766189752063450000016781240006605114763_" class="st1" d="M716.2,207.9
-			c7.4-22.7,42.5-89.3,50.6-105.7c103.7-10.2,126.5,39.6,141.7,137C849.8,225.6,773.8,227.2,716.2,207.9z"/>
-		
-			<text id="ZL_Trigger_00000000206350378518266660000001315160307759857328_" transform="matrix(1.0139 0 0 1 784.2356 179.3992)" class="st4 st9 st10">ZR</text>
-	</g>
-	<g id="R_Trigger_00000085939413106284991650000014018840000393673094_">
-		<path id="Background" class="st1" d="M664,318.5c7-10.1,27.8-78.4,45.4-78.7C1040.8,243.7,897.1,334,664,318.5z"/>
-		<text id="R_Trigger" transform="matrix(1 0 0 1 769.6461 292.8947)" class="st4 st9 st10">R</text>
-	</g>
-	<g id="L_Trigger">
-		<path id="Background_00000043427985111927735300000011910735497762731703_" class="st1" d="M340.6,238.6
-			c17.6,0.3,38.4,68.6,45.4,78.7C152.9,332.8,9.2,242.6,340.6,238.6z"/>
-		
-			<text id="R_Trigger_00000092444210070373642420000009814634285137007748_" transform="matrix(1 0 0 1 253.7327 291.7279)" class="st4 st9 st10">L</text>
-	</g>
-</g>
-</svg>
diff --git a/src/Ryujinx.Ui.Common/Resources/Icon_NCA.png b/src/Ryujinx.Ui.Common/Resources/Icon_NCA.png
deleted file mode 100644
index feae77b9..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Icon_NCA.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Icon_NRO.png b/src/Ryujinx.Ui.Common/Resources/Icon_NRO.png
deleted file mode 100644
index 3a9da621..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Icon_NRO.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Icon_NSO.png b/src/Ryujinx.Ui.Common/Resources/Icon_NSO.png
deleted file mode 100644
index 16de84be..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Icon_NSO.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Icon_NSP.png b/src/Ryujinx.Ui.Common/Resources/Icon_NSP.png
deleted file mode 100644
index 4f98e22e..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Icon_NSP.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Icon_XCI.png b/src/Ryujinx.Ui.Common/Resources/Icon_XCI.png
deleted file mode 100644
index f9c34f47..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Icon_XCI.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Amiibo.png b/src/Ryujinx.Ui.Common/Resources/Logo_Amiibo.png
deleted file mode 100644
index cbee8037..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Amiibo.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Dark.png b/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Dark.png
deleted file mode 100644
index baececa9..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Dark.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Light.png b/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Light.png
deleted file mode 100644
index 25fc892d..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Discord_Light.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Dark.png b/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Dark.png
deleted file mode 100644
index 50b81752..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Dark.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Light.png b/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Light.png
deleted file mode 100644
index 95bc742b..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_GitHub_Light.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Dark.png b/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Dark.png
deleted file mode 100644
index 9a521e3f..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Dark.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Light.png b/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Light.png
deleted file mode 100644
index 44da0ac4..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Patreon_Light.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png b/src/Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png
deleted file mode 100644
index 0e8da15e..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Dark.png b/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Dark.png
deleted file mode 100644
index 66962e7d..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Dark.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Light.png b/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Light.png
deleted file mode 100644
index 040ca169..00000000
Binary files a/src/Ryujinx.Ui.Common/Resources/Logo_Twitter_Light.png and /dev/null differ
diff --git a/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj b/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
deleted file mode 100644
index 387e998b..00000000
--- a/src/Ryujinx.Ui.Common/Ryujinx.Ui.Common.csproj
+++ /dev/null
@@ -1,68 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <None Remove="Resources\Controller_JoyConLeft.svg" />
-    <None Remove="Resources\Controller_JoyConPair.svg" />
-    <None Remove="Resources\Controller_JoyConRight.svg" />
-    <None Remove="Resources\Controller_ProCon.svg" />
-    <None Remove="Resources\Icon_NCA.png" />
-    <None Remove="Resources\Icon_NRO.png" />
-    <None Remove="Resources\Icon_NSO.png" />
-    <None Remove="Resources\Icon_NSP.png" />
-    <None Remove="Resources\Icon_XCI.png" />
-    <None Remove="Resources\Logo_Amiibo.png" />
-    <None Remove="Resources\Logo_Discord.png" />
-    <None Remove="Resources\Logo_GitHub.png" />
-    <None Remove="Resources\Logo_Patreon.png" />
-    <None Remove="Resources\Logo_Ryujinx.png" />
-    <None Remove="Resources\Logo_Twitter.png" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <EmbeddedResource Include="Resources\Controller_JoyConLeft.svg" />
-    <EmbeddedResource Include="Resources\Controller_JoyConPair.svg" />
-    <EmbeddedResource Include="Resources\Controller_JoyConRight.svg" />
-    <EmbeddedResource Include="Resources\Controller_ProCon.svg" />
-    <EmbeddedResource Include="Resources\Icon_NCA.png" />
-    <EmbeddedResource Include="Resources\Icon_NRO.png" />
-    <EmbeddedResource Include="Resources\Icon_NSO.png" />
-    <EmbeddedResource Include="Resources\Icon_NSP.png" />
-    <EmbeddedResource Include="Resources\Icon_XCI.png" />
-    <EmbeddedResource Include="Resources\Logo_Amiibo.png" />
-    <EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
-    <EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
-    <EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
-    <EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
-    <EmbeddedResource Include="Resources\Logo_GitHub_Light.png" />
-    <EmbeddedResource Include="Resources\Logo_Patreon_Dark.png" />
-    <EmbeddedResource Include="Resources\Logo_Patreon_Light.png" />
-    <EmbeddedResource Include="Resources\Logo_Twitter_Dark.png" />
-    <EmbeddedResource Include="Resources\Logo_Twitter_Light.png" />
-  </ItemGroup>
-
-  <ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''">
-    <EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
-  </ItemGroup>
-
-  <ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''">
-    <EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" />
-    <EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="DiscordRichPresence" />
-    <PackageReference Include="securifybv.ShellLink" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
-    <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
-    <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
-  </ItemGroup>
-
-</Project>
diff --git a/src/Ryujinx.Ui.Common/SystemInfo/LinuxSystemInfo.cs b/src/Ryujinx.Ui.Common/SystemInfo/LinuxSystemInfo.cs
deleted file mode 100644
index 5f1ab541..00000000
--- a/src/Ryujinx.Ui.Common/SystemInfo/LinuxSystemInfo.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.SystemInfo
-{
-    [SupportedOSPlatform("linux")]
-    class LinuxSystemInfo : SystemInfo
-    {
-        internal LinuxSystemInfo()
-        {
-            string cpuName = GetCpuidCpuName();
-
-            if (cpuName == null)
-            {
-                var cpuDict = new Dictionary<string, string>(StringComparer.Ordinal)
-                {
-                    ["model name"] = null,
-                    ["Processor"] = null,
-                    ["Hardware"] = null,
-                };
-
-                ParseKeyValues("/proc/cpuinfo", cpuDict);
-
-                cpuName = cpuDict["model name"] ?? cpuDict["Processor"] ?? cpuDict["Hardware"] ?? "Unknown";
-            }
-
-            var memDict = new Dictionary<string, string>(StringComparer.Ordinal)
-            {
-                ["MemTotal"] = null,
-                ["MemAvailable"] = null,
-            };
-
-            ParseKeyValues("/proc/meminfo", memDict);
-
-            // Entries are in KiB
-            ulong.TryParse(memDict["MemTotal"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong totalKiB);
-            ulong.TryParse(memDict["MemAvailable"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong availableKiB);
-
-            CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
-            RamTotal = totalKiB * 1024;
-            RamAvailable = availableKiB * 1024;
-        }
-
-        private static void ParseKeyValues(string filePath, Dictionary<string, string> itemDict)
-        {
-            if (!File.Exists(filePath))
-            {
-                Logger.Error?.Print(LogClass.Application, $"File \"{filePath}\" not found");
-
-                return;
-            }
-
-            int count = itemDict.Count;
-
-            using StreamReader file = new(filePath);
-
-            string line;
-            while ((line = file.ReadLine()) != null)
-            {
-                string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries);
-
-                if (kvPair.Length < 2)
-                {
-                    continue;
-                }
-
-                string key = kvPair[0];
-
-                if (itemDict.TryGetValue(key, out string value) && value == null)
-                {
-                    itemDict[key] = kvPair[1];
-
-                    if (--count <= 0)
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/SystemInfo/MacOSSystemInfo.cs b/src/Ryujinx.Ui.Common/SystemInfo/MacOSSystemInfo.cs
deleted file mode 100644
index 3508ae3a..00000000
--- a/src/Ryujinx.Ui.Common/SystemInfo/MacOSSystemInfo.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-using System.Text;
-
-namespace Ryujinx.Ui.Common.SystemInfo
-{
-    [SupportedOSPlatform("macos")]
-    partial class MacOSSystemInfo : SystemInfo
-    {
-        internal MacOSSystemInfo()
-        {
-            if (SysctlByName("kern.osversion", out string buildRevision) != 0)
-            {
-                buildRevision = "Unknown Build";
-            }
-
-            OsDescription = $"macOS {Environment.OSVersion.Version} ({buildRevision}) ({RuntimeInformation.OSArchitecture})";
-
-            string cpuName = GetCpuidCpuName();
-
-            if (cpuName == null && SysctlByName("machdep.cpu.brand_string", out cpuName) != 0)
-            {
-                cpuName = "Unknown";
-            }
-
-            ulong totalRAM = 0;
-
-            if (SysctlByName("hw.memsize", ref totalRAM) != 0) // Bytes
-            {
-                totalRAM = 0;
-            }
-
-            CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
-            RamTotal = totalRAM;
-            RamAvailable = GetVMInfoAvailableMemory();
-        }
-
-        static ulong GetVMInfoAvailableMemory()
-        {
-            var port = mach_host_self();
-
-            uint pageSize = 0;
-            var result = host_page_size(port, ref pageSize);
-
-            if (result != 0)
-            {
-                Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_page_size() error = {result}");
-                return 0;
-            }
-
-            const int Flavor = 4; // HOST_VM_INFO64
-            uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
-            VMStatistics64 stats = new();
-            result = host_statistics64(port, Flavor, ref stats, ref count);
-
-            if (result != 0)
-            {
-                Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_statistics64() error = {result}");
-                return 0;
-            }
-
-            return (ulong)(stats.FreeCount + stats.InactiveCount) * pageSize;
-        }
-
-        private const string SystemLibraryName = "libSystem.dylib";
-
-        [LibraryImport(SystemLibraryName, SetLastError = true)]
-        private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
-
-        private static int SysctlByName(string name, IntPtr oldValue, ref ulong oldSize)
-        {
-            if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
-            {
-                int err = Marshal.GetLastWin32Error();
-
-                Logger.Error?.Print(LogClass.Application, $"Cannot retrieve '{name}'. Error Code {err}");
-
-                return err;
-            }
-
-            return 0;
-        }
-
-        private static int SysctlByName<T>(string name, ref T oldValue)
-        {
-            unsafe
-            {
-                ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
-
-                return SysctlByName(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
-            }
-        }
-
-        private static int SysctlByName(string name, out string oldValue)
-        {
-            oldValue = default;
-
-            ulong strSize = 0;
-
-            int res = SysctlByName(name, IntPtr.Zero, ref strSize);
-
-            if (res == 0)
-            {
-                byte[] rawData = new byte[strSize];
-
-                unsafe
-                {
-                    fixed (byte* rawDataPtr = rawData)
-                    {
-                        res = SysctlByName(name, (IntPtr)rawDataPtr, ref strSize);
-                    }
-
-                    if (res == 0)
-                    {
-                        oldValue = Encoding.ASCII.GetString(rawData);
-                    }
-                }
-            }
-
-            return res;
-        }
-
-        [LibraryImport(SystemLibraryName, SetLastError = true)]
-        private static partial uint mach_host_self();
-
-        [LibraryImport(SystemLibraryName, SetLastError = true)]
-        private static partial int host_page_size(uint host, ref uint out_page_size);
-
-        [StructLayout(LayoutKind.Sequential, Pack = 8)]
-        struct VMStatistics64
-        {
-            public uint FreeCount;
-            public uint ActiveCount;
-            public uint InactiveCount;
-            public uint WireCount;
-            public ulong ZeroFillCount;
-            public ulong Reactivations;
-            public ulong Pageins;
-            public ulong Pageouts;
-            public ulong Faults;
-            public ulong CowFaults;
-            public ulong Lookups;
-            public ulong Hits;
-            public ulong Purges;
-            public uint PurgeableCount;
-            public uint SpeculativeCount;
-            public ulong Decompressions;
-            public ulong Compressions;
-            public ulong Swapins;
-            public ulong Swapouts;
-            public uint CompressorPageCount;
-            public uint ThrottledCount;
-            public uint ExternalPageCount;
-            public uint InternalPageCount;
-            public ulong TotalUncompressedPagesInCompressor;
-        }
-
-        [LibraryImport(SystemLibraryName, SetLastError = true)]
-        private static partial int host_statistics64(uint hostPriv, int hostFlavor, ref VMStatistics64 hostInfo64Out, ref uint hostInfo64OutCnt);
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/SystemInfo/SystemInfo.cs b/src/Ryujinx.Ui.Common/SystemInfo/SystemInfo.cs
deleted file mode 100644
index e78db8af..00000000
--- a/src/Ryujinx.Ui.Common/SystemInfo/SystemInfo.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using Ryujinx.Common.Logging;
-using Ryujinx.Ui.Common.Helper;
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Text;
-
-namespace Ryujinx.Ui.Common.SystemInfo
-{
-    public class SystemInfo
-    {
-        public string OsDescription { get; protected set; }
-        public string CpuName { get; protected set; }
-        public ulong RamTotal { get; protected set; }
-        public ulong RamAvailable { get; protected set; }
-        protected static int LogicalCoreCount => Environment.ProcessorCount;
-
-        protected SystemInfo()
-        {
-            OsDescription = $"{RuntimeInformation.OSDescription} ({RuntimeInformation.OSArchitecture})";
-            CpuName = "Unknown";
-        }
-
-        private static string ToGBString(ulong bytesValue) => (bytesValue == 0) ? "Unknown" : ValueFormatUtils.FormatFileSize((long)bytesValue, ValueFormatUtils.FileSizeUnits.Gibibytes);
-
-        public void Print()
-        {
-            Logger.Notice.Print(LogClass.Application, $"Operating System: {OsDescription}");
-            Logger.Notice.Print(LogClass.Application, $"CPU: {CpuName}");
-            Logger.Notice.Print(LogClass.Application, $"RAM: Total {ToGBString(RamTotal)} ; Available {ToGBString(RamAvailable)}");
-        }
-
-        public static SystemInfo Gather()
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                return new WindowsSystemInfo();
-            }
-            else if (OperatingSystem.IsLinux())
-            {
-                return new LinuxSystemInfo();
-            }
-            else if (OperatingSystem.IsMacOS())
-            {
-                return new MacOSSystemInfo();
-            }
-
-            Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform");
-
-            return new SystemInfo();
-        }
-
-        // x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004.
-        internal static string GetCpuidCpuName()
-        {
-            if (!X86Base.IsSupported)
-            {
-                return null;
-            }
-
-            // Check if CPU supports the query
-            if ((uint)X86Base.CpuId(unchecked((int)0x80000000), 0).Eax < 0x80000004)
-            {
-                return null;
-            }
-
-            int[] regs = new int[12];
-
-            for (uint i = 0; i < 3; ++i)
-            {
-                (regs[4 * i], regs[4 * i + 1], regs[4 * i + 2], regs[4 * i + 3]) = X86Base.CpuId((int)(0x80000002 + i), 0);
-            }
-
-            string name = Encoding.ASCII.GetString(MemoryMarshal.Cast<int, byte>(regs)).Replace('\0', ' ').Trim();
-
-            return string.IsNullOrEmpty(name) ? null : name;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/SystemInfo/WindowsSystemInfo.cs b/src/Ryujinx.Ui.Common/SystemInfo/WindowsSystemInfo.cs
deleted file mode 100644
index 9bb0fbf7..00000000
--- a/src/Ryujinx.Ui.Common/SystemInfo/WindowsSystemInfo.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Management;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Common.SystemInfo
-{
-    [SupportedOSPlatform("windows")]
-    partial class WindowsSystemInfo : SystemInfo
-    {
-        internal WindowsSystemInfo()
-        {
-            CpuName = $"{GetCpuidCpuName() ?? GetCpuNameWMI()} ; {LogicalCoreCount} logical"; // WMI is very slow
-            (RamTotal, RamAvailable) = GetMemoryStats();
-        }
-
-        private static (ulong Total, ulong Available) GetMemoryStats()
-        {
-            MemoryStatusEx memStatus = new();
-            if (GlobalMemoryStatusEx(ref memStatus))
-            {
-                return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
-            }
-
-            Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
-
-            return (0, 0);
-        }
-
-        private static string GetCpuNameWMI()
-        {
-            ManagementObjectCollection cpuObjs = GetWMIObjects("root\\CIMV2", "SELECT * FROM Win32_Processor");
-
-            if (cpuObjs != null)
-            {
-                foreach (var cpuObj in cpuObjs)
-                {
-                    return cpuObj["Name"].ToString().Trim();
-                }
-            }
-
-            return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim();
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        private struct MemoryStatusEx
-        {
-            public uint Length;
-            public uint MemoryLoad;
-            public ulong TotalPhys;
-            public ulong AvailPhys;
-            public ulong TotalPageFile;
-            public ulong AvailPageFile;
-            public ulong TotalVirtual;
-            public ulong AvailVirtual;
-            public ulong AvailExtendedVirtual;
-
-            public MemoryStatusEx()
-            {
-                Length = (uint)Marshal.SizeOf<MemoryStatusEx>();
-            }
-        }
-
-        [LibraryImport("kernel32.dll", SetLastError = true)]
-        [return: MarshalAs(UnmanagedType.Bool)]
-        private static partial bool GlobalMemoryStatusEx(ref MemoryStatusEx lpBuffer);
-
-        private static ManagementObjectCollection GetWMIObjects(string scope, string query)
-        {
-            try
-            {
-                return new ManagementObjectSearcher(scope, query).Get();
-            }
-            catch (PlatformNotSupportedException ex)
-            {
-                Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
-            }
-            catch (COMException ex)
-            {
-                Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
-            }
-
-            return null;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.Common/UserError.cs b/src/Ryujinx.Ui.Common/UserError.cs
deleted file mode 100644
index 832aae9d..00000000
--- a/src/Ryujinx.Ui.Common/UserError.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-namespace Ryujinx.Ui.Common
-{
-    /// <summary>
-    /// Represent a common error that could be reported to the user by the emulator.
-    /// </summary>
-    public enum UserError
-    {
-        /// <summary>
-        /// No error to report.
-        /// </summary>
-        Success = 0x0,
-
-        /// <summary>
-        /// No keys are present.
-        /// </summary>
-        NoKeys = 0x1,
-
-        /// <summary>
-        /// No firmware is installed.
-        /// </summary>
-        NoFirmware = 0x2,
-
-        /// <summary>
-        /// Firmware parsing failed.
-        /// </summary>
-        /// <remarks>Most likely related to keys.</remarks>
-        FirmwareParsingFailed = 0x3,
-
-        /// <summary>
-        /// No application was found at the given path.
-        /// </summary>
-        ApplicationNotFound = 0x4,
-
-        /// <summary>
-        /// An unknown error.
-        /// </summary>
-        Unknown = 0xDEAD,
-    }
-}
diff --git a/src/Ryujinx.Ui.LocaleGenerator/LocaleGenerator.cs b/src/Ryujinx.Ui.LocaleGenerator/LocaleGenerator.cs
deleted file mode 100644
index 27573a8f..00000000
--- a/src/Ryujinx.Ui.LocaleGenerator/LocaleGenerator.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Microsoft.CodeAnalysis;
-using System.Linq;
-using System.Text;
-
-namespace Ryujinx.Ui.LocaleGenerator
-{
-    [Generator]
-    public class LocaleGenerator : IIncrementalGenerator
-    {
-        public void Initialize(IncrementalGeneratorInitializationContext context)
-        {
-            var englishLocaleFile = context.AdditionalTextsProvider.Where(static x => x.Path.EndsWith("en_US.json"));
-
-            IncrementalValuesProvider<string> contents = englishLocaleFile.Select((text, cancellationToken) => text.GetText(cancellationToken)!.ToString());
-
-            context.RegisterSourceOutput(contents, (spc, content) =>
-            {
-                var lines = content.Split('\n').Where(x => x.Trim().StartsWith("\"")).Select(x => x.Split(':')[0].Trim().Replace("\"", ""));
-                StringBuilder enumSourceBuilder = new();
-                enumSourceBuilder.AppendLine("namespace Ryujinx.Ava.Common.Locale;");
-                enumSourceBuilder.AppendLine("internal enum LocaleKeys");
-                enumSourceBuilder.AppendLine("{");
-                foreach (var line in lines)
-                {
-                    enumSourceBuilder.AppendLine($"    {line},");
-                }
-                enumSourceBuilder.AppendLine("}");
-
-                spc.AddSource("LocaleKeys", enumSourceBuilder.ToString());
-            });
-        }
-    }
-}
diff --git a/src/Ryujinx.Ui.LocaleGenerator/Ryujinx.Ui.LocaleGenerator.csproj b/src/Ryujinx.Ui.LocaleGenerator/Ryujinx.Ui.LocaleGenerator.csproj
deleted file mode 100644
index 05cbc764..00000000
--- a/src/Ryujinx.Ui.LocaleGenerator/Ryujinx.Ui.LocaleGenerator.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-    <Nullable>enable</Nullable>
-    <LangVersion>latest</LangVersion>
-    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
-    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
-  </ItemGroup>
-
-</Project>
diff --git a/src/Ryujinx/Modules/Updater/UpdateDialog.cs b/src/Ryujinx/Modules/Updater/UpdateDialog.cs
index 0057761b..ec24cdc8 100644
--- a/src/Ryujinx/Modules/Updater/UpdateDialog.cs
+++ b/src/Ryujinx/Modules/Updater/UpdateDialog.cs
@@ -2,9 +2,9 @@ using Gdk;
 using Gtk;
 using Ryujinx.Common;
 using Ryujinx.Common.Configuration;
-using Ryujinx.Ui;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
+using Ryujinx.UI;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
 using System;
 using System.Diagnostics;
 using System.Reflection;
@@ -34,7 +34,7 @@ namespace Ryujinx.Modules
             _mainWindow = mainWindow;
             _buildUrl = buildUrl;
 
-            Icon = new Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
+            Icon = new Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
             MainText.Text = "Do you want to update Ryujinx to the latest version?";
             SecondaryText.Text = $"{Program.Version} -> {newVersion}";
 
diff --git a/src/Ryujinx/Modules/Updater/Updater.cs b/src/Ryujinx/Modules/Updater/Updater.cs
index 2fed4362..16fbc36a 100644
--- a/src/Ryujinx/Modules/Updater/Updater.cs
+++ b/src/Ryujinx/Modules/Updater/Updater.cs
@@ -5,9 +5,9 @@ using ICSharpCode.SharpZipLib.Zip;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
-using Ryujinx.Ui;
-using Ryujinx.Ui.Common.Models.Github;
-using Ryujinx.Ui.Widgets;
+using Ryujinx.UI;
+using Ryujinx.UI.Common.Models.Github;
+using Ryujinx.UI.Widgets;
 using System;
 using System.Collections.Generic;
 using System.IO;
diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs
index 3b5cd770..1845c512 100644
--- a/src/Ryujinx/Program.cs
+++ b/src/Ryujinx/Program.cs
@@ -6,12 +6,12 @@ using Ryujinx.Common.Logging;
 using Ryujinx.Common.SystemInterop;
 using Ryujinx.Modules;
 using Ryujinx.SDL2.Common;
-using Ryujinx.Ui;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Common.SystemInfo;
-using Ryujinx.Ui.Widgets;
+using Ryujinx.UI;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Common.SystemInfo;
+using Ryujinx.UI.Widgets;
 using SixLabors.ImageSharp.Formats.Jpeg;
 using System;
 using System.Collections.Generic;
diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj
index 830e0e6c..68bf9898 100644
--- a/src/Ryujinx/Ryujinx.csproj
+++ b/src/Ryujinx/Ryujinx.csproj
@@ -45,7 +45,7 @@
     <ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
     <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
     <ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
-    <ProjectReference Include="..\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj" />
+    <ProjectReference Include="..\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj" />
   </ItemGroup>
 
   <ItemGroup>
@@ -80,24 +80,24 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <None Remove="Ui\MainWindow.glade" />
-    <None Remove="Ui\Widgets\ProfileDialog.glade" />
-    <None Remove="Ui\Windows\CheatWindow.glade" />
-    <None Remove="Ui\Windows\ControllerWindow.glade" />
-    <None Remove="Ui\Windows\DlcWindow.glade" />
-    <None Remove="Ui\Windows\SettingsWindow.glade" />
-    <None Remove="Ui\Windows\TitleUpdateWindow.glade" />
+    <None Remove="UI\MainWindow.glade" />
+    <None Remove="UI\Widgets\ProfileDialog.glade" />
+    <None Remove="UI\Windows\CheatWindow.glade" />
+    <None Remove="UI\Windows\ControllerWindow.glade" />
+    <None Remove="UI\Windows\DlcWindow.glade" />
+    <None Remove="UI\Windows\SettingsWindow.glade" />
+    <None Remove="UI\Windows\TitleUpdateWindow.glade" />
     <None Remove="Modules\Updater\UpdateDialog.glade" />
   </ItemGroup>
 
   <ItemGroup>
-    <EmbeddedResource Include="Ui\MainWindow.glade" />
-    <EmbeddedResource Include="Ui\Widgets\ProfileDialog.glade" />
-    <EmbeddedResource Include="Ui\Windows\CheatWindow.glade" />
-    <EmbeddedResource Include="Ui\Windows\ControllerWindow.glade" />
-    <EmbeddedResource Include="Ui\Windows\DlcWindow.glade" />
-    <EmbeddedResource Include="Ui\Windows\SettingsWindow.glade" />
-    <EmbeddedResource Include="Ui\Windows\TitleUpdateWindow.glade" />
+    <EmbeddedResource Include="UI\MainWindow.glade" />
+    <EmbeddedResource Include="UI\Widgets\ProfileDialog.glade" />
+    <EmbeddedResource Include="UI\Windows\CheatWindow.glade" />
+    <EmbeddedResource Include="UI\Windows\ControllerWindow.glade" />
+    <EmbeddedResource Include="UI\Windows\DlcWindow.glade" />
+    <EmbeddedResource Include="UI\Windows\SettingsWindow.glade" />
+    <EmbeddedResource Include="UI\Windows\TitleUpdateWindow.glade" />
     <EmbeddedResource Include="Modules\Updater\UpdateDialog.glade" />
   </ItemGroup>
 
diff --git a/src/Ryujinx/UI/Applet/ErrorAppletDialog.cs b/src/Ryujinx/UI/Applet/ErrorAppletDialog.cs
new file mode 100644
index 00000000..7f8cc0e9
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/ErrorAppletDialog.cs
@@ -0,0 +1,31 @@
+using Gtk;
+using Ryujinx.UI.Common.Configuration;
+using System.Reflection;
+
+namespace Ryujinx.UI.Applet
+{
+    internal class ErrorAppletDialog : MessageDialog
+    {
+        public ErrorAppletDialog(Window parentWindow, DialogFlags dialogFlags, MessageType messageType, string[] buttons) : base(parentWindow, dialogFlags, messageType, ButtonsType.None, null)
+        {
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            int responseId = 0;
+
+            if (buttons != null)
+            {
+                foreach (string buttonText in buttons)
+                {
+                    AddButton(buttonText, responseId);
+                    responseId++;
+                }
+            }
+            else
+            {
+                AddButton("OK", 0);
+            }
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Applet/GtkDynamicTextInputHandler.cs b/src/Ryujinx/UI/Applet/GtkDynamicTextInputHandler.cs
new file mode 100644
index 00000000..0e560b78
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/GtkDynamicTextInputHandler.cs
@@ -0,0 +1,108 @@
+using Gtk;
+using Ryujinx.HLE.UI;
+using Ryujinx.Input.GTK3;
+using Ryujinx.UI.Widgets;
+using System.Threading;
+
+namespace Ryujinx.UI.Applet
+{
+    /// <summary>
+    /// Class that forwards key events to a GTK Entry so they can be processed into text.
+    /// </summary>
+    internal class GtkDynamicTextInputHandler : IDynamicTextInputHandler
+    {
+        private readonly Window _parent;
+        private readonly OffscreenWindow _inputToTextWindow = new();
+        private readonly RawInputToTextEntry _inputToTextEntry = new();
+
+        private bool _canProcessInput;
+
+        public event DynamicTextChangedHandler TextChangedEvent;
+        public event KeyPressedHandler KeyPressedEvent;
+        public event KeyReleasedHandler KeyReleasedEvent;
+
+        public bool TextProcessingEnabled
+        {
+            get
+            {
+                return Volatile.Read(ref _canProcessInput);
+            }
+
+            set
+            {
+                Volatile.Write(ref _canProcessInput, value);
+            }
+        }
+
+        public GtkDynamicTextInputHandler(Window parent)
+        {
+            _parent = parent;
+            _parent.KeyPressEvent += HandleKeyPressEvent;
+            _parent.KeyReleaseEvent += HandleKeyReleaseEvent;
+
+            _inputToTextWindow.Add(_inputToTextEntry);
+
+            _inputToTextEntry.TruncateMultiline = true;
+
+            // Start with input processing turned off so the text box won't accumulate text 
+            // if the user is playing on the keyboard.
+            _canProcessInput = false;
+        }
+
+        [GLib.ConnectBefore()]
+        private void HandleKeyPressEvent(object o, KeyPressEventArgs args)
+        {
+            var key = (Ryujinx.Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
+
+            if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
+            {
+                return;
+            }
+
+            if (_canProcessInput)
+            {
+                _inputToTextEntry.SendKeyPressEvent(o, args);
+                _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
+                TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
+            }
+        }
+
+        [GLib.ConnectBefore()]
+        private void HandleKeyReleaseEvent(object o, KeyReleaseEventArgs args)
+        {
+            var key = (Ryujinx.Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
+
+            if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
+            {
+                return;
+            }
+
+            if (_canProcessInput)
+            {
+                // TODO (caian): This solution may have problems if the pause is sent after a key press
+                // and before a key release. But for now GTK Entry does not seem to use release events.
+                _inputToTextEntry.SendKeyReleaseEvent(o, args);
+                _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
+                TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
+            }
+        }
+
+        public void SetText(string text, int cursorBegin)
+        {
+            _inputToTextEntry.Text = text;
+            _inputToTextEntry.Position = cursorBegin;
+        }
+
+        public void SetText(string text, int cursorBegin, int cursorEnd)
+        {
+            _inputToTextEntry.Text = text;
+            _inputToTextEntry.SelectRegion(cursorBegin, cursorEnd);
+        }
+
+        public void Dispose()
+        {
+            _parent.KeyPressEvent -= HandleKeyPressEvent;
+            _parent.KeyReleaseEvent -= HandleKeyReleaseEvent;
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Applet/GtkHostUIHandler.cs b/src/Ryujinx/UI/Applet/GtkHostUIHandler.cs
new file mode 100644
index 00000000..1d918d21
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/GtkHostUIHandler.cs
@@ -0,0 +1,200 @@
+using Gtk;
+using Ryujinx.HLE.HOS.Applets;
+using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
+using Ryujinx.HLE.UI;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Threading;
+
+namespace Ryujinx.UI.Applet
+{
+    internal class GtkHostUIHandler : IHostUIHandler
+    {
+        private readonly Window _parent;
+
+        public IHostUITheme HostUITheme { get; }
+
+        public GtkHostUIHandler(Window parent)
+        {
+            _parent = parent;
+
+            HostUITheme = new GtkHostUITheme(parent);
+        }
+
+        public bool DisplayMessageDialog(ControllerAppletUIArgs args)
+        {
+            string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
+
+            string message = $"Application requests <b>{playerCount}</b> player(s) with:\n\n"
+                           + $"<tt><b>TYPES:</b> {args.SupportedStyles}</tt>\n\n"
+                           + $"<tt><b>PLAYERS:</b> {string.Join(", ", args.SupportedPlayers)}</tt>\n\n"
+                           + (args.IsDocked ? "Docked mode set. <tt>Handheld</tt> is also invalid.\n\n" : "")
+                           + "<i>Please reconfigure Input now and then press OK.</i>";
+
+            return DisplayMessageDialog("Controller Applet", message);
+        }
+
+        public bool DisplayMessageDialog(string title, string message)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool okPressed = false;
+
+            Application.Invoke(delegate
+            {
+                MessageDialog msgDialog = null;
+
+                try
+                {
+                    msgDialog = new MessageDialog(_parent, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
+                    {
+                        Title = title,
+                        Text = message,
+                        UseMarkup = true,
+                    };
+
+                    msgDialog.SetDefaultSize(400, 0);
+
+                    msgDialog.Response += (object o, ResponseArgs args) =>
+                    {
+                        if (args.ResponseId == ResponseType.Ok)
+                        {
+                            okPressed = true;
+                        }
+
+                        dialogCloseEvent.Set();
+                        msgDialog?.Dispose();
+                    };
+
+                    msgDialog.Show();
+                }
+                catch (Exception ex)
+                {
+                    GtkDialog.CreateErrorDialog($"Error displaying Message Dialog: {ex}");
+
+                    dialogCloseEvent.Set();
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            return okPressed;
+        }
+
+        public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool okPressed = false;
+            bool error = false;
+            string inputText = args.InitialText ?? "";
+
+            Application.Invoke(delegate
+            {
+                try
+                {
+                    var swkbdDialog = new SwkbdAppletDialog(_parent)
+                    {
+                        Title = "Software Keyboard",
+                        Text = args.HeaderText,
+                        SecondaryText = args.SubtitleText,
+                    };
+
+                    swkbdDialog.InputEntry.Text = inputText;
+                    swkbdDialog.InputEntry.PlaceholderText = args.GuideText;
+                    swkbdDialog.OkButton.Label = args.SubmitText;
+
+                    swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
+                    swkbdDialog.SetInputValidation(args.KeyboardMode);
+
+                    if (swkbdDialog.Run() == (int)ResponseType.Ok)
+                    {
+                        inputText = swkbdDialog.InputEntry.Text;
+                        okPressed = true;
+                    }
+
+                    swkbdDialog.Dispose();
+                }
+                catch (Exception ex)
+                {
+                    error = true;
+
+                    GtkDialog.CreateErrorDialog($"Error displaying Software Keyboard: {ex}");
+                }
+                finally
+                {
+                    dialogCloseEvent.Set();
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            userText = error ? null : inputText;
+
+            return error || okPressed;
+        }
+
+        public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value)
+        {
+            device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
+            ((MainWindow)_parent).RendererWidget?.Exit();
+        }
+
+        public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
+        {
+            ManualResetEvent dialogCloseEvent = new(false);
+
+            bool showDetails = false;
+
+            Application.Invoke(delegate
+            {
+                try
+                {
+                    ErrorAppletDialog msgDialog = new(_parent, DialogFlags.DestroyWithParent, MessageType.Error, buttons)
+                    {
+                        Title = title,
+                        Text = message,
+                        UseMarkup = true,
+                        WindowPosition = WindowPosition.CenterAlways,
+                    };
+
+                    msgDialog.SetDefaultSize(400, 0);
+
+                    msgDialog.Response += (object o, ResponseArgs args) =>
+                    {
+                        if (buttons != null)
+                        {
+                            if (buttons.Length > 1)
+                            {
+                                if (args.ResponseId != (ResponseType)(buttons.Length - 1))
+                                {
+                                    showDetails = true;
+                                }
+                            }
+                        }
+
+                        dialogCloseEvent.Set();
+                        msgDialog?.Dispose();
+                    };
+
+                    msgDialog.Show();
+                }
+                catch (Exception ex)
+                {
+                    GtkDialog.CreateErrorDialog($"Error displaying ErrorApplet Dialog: {ex}");
+
+                    dialogCloseEvent.Set();
+                }
+            });
+
+            dialogCloseEvent.WaitOne();
+
+            return showDetails;
+        }
+
+        public IDynamicTextInputHandler CreateDynamicTextInputHandler()
+        {
+            return new GtkDynamicTextInputHandler(_parent);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Applet/GtkHostUITheme.cs b/src/Ryujinx/UI/Applet/GtkHostUITheme.cs
new file mode 100644
index 00000000..52d1123b
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/GtkHostUITheme.cs
@@ -0,0 +1,90 @@
+using Gtk;
+using Ryujinx.HLE.UI;
+using System.Diagnostics;
+
+namespace Ryujinx.UI.Applet
+{
+    internal class GtkHostUITheme : IHostUITheme
+    {
+        private const int RenderSurfaceWidth = 32;
+        private const int RenderSurfaceHeight = 32;
+
+        public string FontFamily { get; private set; }
+
+        public ThemeColor DefaultBackgroundColor { get; }
+        public ThemeColor DefaultForegroundColor { get; }
+        public ThemeColor DefaultBorderColor { get; }
+        public ThemeColor SelectionBackgroundColor { get; }
+        public ThemeColor SelectionForegroundColor { get; }
+
+        public GtkHostUITheme(Window parent)
+        {
+            Entry entry = new();
+            entry.SetStateFlags(StateFlags.Selected, true);
+
+            // Get the font and some colors directly from GTK.
+            FontFamily = entry.PangoContext.FontDescription.Family;
+
+            // Get foreground colors from the style context.
+
+            var defaultForegroundColor = entry.StyleContext.GetColor(StateFlags.Normal);
+            var selectedForegroundColor = entry.StyleContext.GetColor(StateFlags.Selected);
+
+            DefaultForegroundColor = new ThemeColor((float)defaultForegroundColor.Alpha, (float)defaultForegroundColor.Red, (float)defaultForegroundColor.Green, (float)defaultForegroundColor.Blue);
+            SelectionForegroundColor = new ThemeColor((float)selectedForegroundColor.Alpha, (float)selectedForegroundColor.Red, (float)selectedForegroundColor.Green, (float)selectedForegroundColor.Blue);
+
+            ListBoxRow row = new();
+            row.SetStateFlags(StateFlags.Selected, true);
+
+            // Request the main thread to render some UI elements to an image to get an approximation for the color.
+            // NOTE (caian): This will only take the color of the top-left corner of the background, which may be incorrect
+            // if someone provides a custom style with a gradient or image.
+
+            using (var surface = new Cairo.ImageSurface(Cairo.Format.Argb32, RenderSurfaceWidth, RenderSurfaceHeight))
+            using (var context = new Cairo.Context(surface))
+            {
+                context.SetSourceRGBA(1, 1, 1, 1);
+                context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
+                context.Fill();
+
+                // The background color must be from the main Window because entry uses a different color.
+                parent.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
+
+                DefaultBackgroundColor = ToThemeColor(surface.Data);
+
+                context.SetSourceRGBA(1, 1, 1, 1);
+                context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
+                context.Fill();
+
+                // Use the background color of the list box row when selected as the text box frame color because they are the
+                // same in the default theme.
+                row.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
+
+                DefaultBorderColor = ToThemeColor(surface.Data);
+            }
+
+            // Use the border color as the text selection color.
+            SelectionBackgroundColor = DefaultBorderColor;
+        }
+
+        private static ThemeColor ToThemeColor(byte[] data)
+        {
+            Debug.Assert(data.Length == 4 * RenderSurfaceWidth * RenderSurfaceHeight);
+
+            // Take the center-bottom pixel of the surface.
+            int position = 4 * (RenderSurfaceWidth * (RenderSurfaceHeight - 1) + RenderSurfaceWidth / 2);
+
+            if (position + 4 > data.Length)
+            {
+                return new ThemeColor(1, 0, 0, 0);
+            }
+
+            float a = data[position + 3] / 255.0f;
+            float r = data[position + 2] / 255.0f;
+            float g = data[position + 1] / 255.0f;
+            float b = data[position + 0] / 255.0f;
+
+            return new ThemeColor(a, r, g, b);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Applet/SwkbdAppletDialog.cs b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.cs
new file mode 100644
index 00000000..8045da91
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.cs
@@ -0,0 +1,127 @@
+using Gtk;
+using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
+using System;
+using System.Linq;
+
+namespace Ryujinx.UI.Applet
+{
+    public class SwkbdAppletDialog : MessageDialog
+    {
+        private int _inputMin;
+        private int _inputMax;
+#pragma warning disable IDE0052 // Remove unread private member
+        private KeyboardMode _mode;
+#pragma warning restore IDE0052
+
+        private string _validationInfoText = "";
+
+        private Predicate<int> _checkLength = _ => true;
+        private Predicate<string> _checkInput = _ => true;
+
+        private readonly Label _validationInfo;
+
+        public Entry InputEntry { get; }
+        public Button OkButton { get; }
+        public Button CancelButton { get; }
+
+        public SwkbdAppletDialog(Window parent) : base(parent, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.None, null)
+        {
+            SetDefaultSize(300, 0);
+
+            _validationInfo = new Label()
+            {
+                Visible = false,
+            };
+
+            InputEntry = new Entry()
+            {
+                Visible = true,
+            };
+
+            InputEntry.Activated += OnInputActivated;
+            InputEntry.Changed += OnInputChanged;
+
+            OkButton = (Button)AddButton("OK", ResponseType.Ok);
+            CancelButton = (Button)AddButton("Cancel", ResponseType.Cancel);
+
+            ((Box)MessageArea).PackEnd(_validationInfo, true, true, 0);
+            ((Box)MessageArea).PackEnd(InputEntry, true, true, 4);
+        }
+
+        private void ApplyValidationInfo()
+        {
+            _validationInfo.Visible = !string.IsNullOrEmpty(_validationInfoText);
+            _validationInfo.Markup = _validationInfoText;
+        }
+
+        public void SetInputLengthValidation(int min, int max)
+        {
+            _inputMin = Math.Min(min, max);
+            _inputMax = Math.Max(min, max);
+
+            _validationInfo.Visible = false;
+
+            if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
+            {
+                _validationInfo.Visible = false;
+
+                _checkLength = _ => true;
+            }
+            else if (_inputMin > 0 && _inputMax == int.MaxValue)
+            {
+                _validationInfoText = $"<i>Must be at least {_inputMin} characters long.</i> ";
+
+                _checkLength = length => _inputMin <= length;
+            }
+            else
+            {
+                _validationInfoText = $"<i>Must be {_inputMin}-{_inputMax} characters long.</i> ";
+
+                _checkLength = length => _inputMin <= length && length <= _inputMax;
+            }
+
+            ApplyValidationInfo();
+            OnInputChanged(this, EventArgs.Empty);
+        }
+
+        public void SetInputValidation(KeyboardMode mode)
+        {
+            _mode = mode;
+
+            switch (mode)
+            {
+                case KeyboardMode.Numeric:
+                    _validationInfoText += "<i>Must be 0-9 or '.' only.</i>";
+                    _checkInput = text => text.All(NumericCharacterValidation.IsNumeric);
+                    break;
+                case KeyboardMode.Alphabet:
+                    _validationInfoText += "<i>Must be non CJK-characters only.</i>";
+                    _checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
+                    break;
+                case KeyboardMode.ASCII:
+                    _validationInfoText += "<i>Must be ASCII text only.</i>";
+                    _checkInput = text => text.All(char.IsAscii);
+                    break;
+                default:
+                    _checkInput = _ => true;
+                    break;
+            }
+
+            ApplyValidationInfo();
+            OnInputChanged(this, EventArgs.Empty);
+        }
+
+        private void OnInputActivated(object sender, EventArgs e)
+        {
+            if (OkButton.IsSensitive)
+            {
+                Respond(ResponseType.Ok);
+            }
+        }
+
+        private void OnInputChanged(object sender, EventArgs e)
+        {
+            OkButton.Sensitive = _checkLength(InputEntry.Text.Length) && _checkInput(InputEntry.Text);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Helper/MetalHelper.cs b/src/Ryujinx/UI/Helper/MetalHelper.cs
new file mode 100644
index 00000000..c2c32d3a
--- /dev/null
+++ b/src/Ryujinx/UI/Helper/MetalHelper.cs
@@ -0,0 +1,135 @@
+using Gdk;
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Helper
+{
+    public delegate void UpdateBoundsCallbackDelegate(Window window);
+
+    [SupportedOSPlatform("macos")]
+    static partial class MetalHelper
+    {
+        private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
+
+        private readonly struct Selector
+        {
+            public readonly IntPtr NativePtr;
+
+            public unsafe Selector(string value)
+            {
+                int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
+                byte* data = stackalloc byte[size];
+
+                fixed (char* pValue = value)
+                {
+                    System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
+                }
+
+                NativePtr = sel_registerName(data);
+            }
+
+            public static implicit operator Selector(string value) => new(value);
+        }
+
+        private static unsafe IntPtr GetClass(string value)
+        {
+            int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
+            byte* data = stackalloc byte[size];
+
+            fixed (char* pValue = value)
+            {
+                System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
+            }
+
+            return objc_getClass(data);
+        }
+
+        private struct NsPoint
+        {
+            public double X;
+            public double Y;
+
+            public NsPoint(double x, double y)
+            {
+                X = x;
+                Y = y;
+            }
+        }
+
+        private struct NsRect
+        {
+            public NsPoint Pos;
+            public NsPoint Size;
+
+            public NsRect(double x, double y, double width, double height)
+            {
+                Pos = new NsPoint(x, y);
+                Size = new NsPoint(width, height);
+            }
+        }
+
+        public static IntPtr GetMetalLayer(Display display, Window window, out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
+        {
+            nsView = gdk_quartz_window_get_nsview(window.Handle);
+
+            // Create a new CAMetalLayer.
+            IntPtr layerClass = GetClass("CAMetalLayer");
+            IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
+            objc_msgSend(metalLayer, "init");
+
+            // Create a child NSView to render into.
+            IntPtr nsViewClass = GetClass("NSView");
+            IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
+            objc_msgSend(child, "init", new NsRect());
+
+            // Add it as a child.
+            objc_msgSend(nsView, "addSubview:", child);
+
+            // Make its renderer our metal layer.
+            objc_msgSend(child, "setWantsLayer:", (byte)1);
+            objc_msgSend(child, "setLayer:", metalLayer);
+            objc_msgSend(metalLayer, "setContentsScale:", (double)display.GetMonitorAtWindow(window).ScaleFactor);
+
+            // Set the frame position/location.
+            updateBounds = (Window window) =>
+            {
+                window.GetPosition(out int x, out int y);
+                int width = window.Width;
+                int height = window.Height;
+                objc_msgSend(child, "setFrame:", new NsRect(x, y, width, height));
+            };
+
+            updateBounds(window);
+
+            return metalLayer;
+        }
+
+        [LibraryImport(LibObjCImport)]
+        private static unsafe partial IntPtr sel_registerName(byte* data);
+
+        [LibraryImport(LibObjCImport)]
+        private static unsafe partial IntPtr objc_getClass(byte* data);
+
+        [LibraryImport(LibObjCImport)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector);
+
+        [LibraryImport(LibObjCImport)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
+
+        [LibraryImport(LibObjCImport)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
+
+        [LibraryImport(LibObjCImport)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, NsRect point);
+
+        [LibraryImport(LibObjCImport)]
+        private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
+
+        [LibraryImport(LibObjCImport, EntryPoint = "objc_msgSend")]
+        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
+
+        [LibraryImport("libgdk-3.0.dylib")]
+        private static partial IntPtr gdk_quartz_window_get_nsview(IntPtr gdkWindow);
+    }
+}
diff --git a/src/Ryujinx/UI/Helper/SortHelper.cs b/src/Ryujinx/UI/Helper/SortHelper.cs
new file mode 100644
index 00000000..3e3fbeaa
--- /dev/null
+++ b/src/Ryujinx/UI/Helper/SortHelper.cs
@@ -0,0 +1,33 @@
+using Gtk;
+using Ryujinx.UI.Common.Helper;
+using System;
+
+namespace Ryujinx.UI.Helper
+{
+    static class SortHelper
+    {
+        public static int TimePlayedSort(ITreeModel model, TreeIter a, TreeIter b)
+        {
+            TimeSpan aTimeSpan = ValueFormatUtils.ParseTimeSpan(model.GetValue(a, 5).ToString());
+            TimeSpan bTimeSpan = ValueFormatUtils.ParseTimeSpan(model.GetValue(b, 5).ToString());
+
+            return TimeSpan.Compare(aTimeSpan, bTimeSpan);
+        }
+
+        public static int LastPlayedSort(ITreeModel model, TreeIter a, TreeIter b)
+        {
+            DateTime aDateTime = ValueFormatUtils.ParseDateTime(model.GetValue(a, 6).ToString());
+            DateTime bDateTime = ValueFormatUtils.ParseDateTime(model.GetValue(b, 6).ToString());
+
+            return DateTime.Compare(aDateTime, bDateTime);
+        }
+
+        public static int FileSizeSort(ITreeModel model, TreeIter a, TreeIter b)
+        {
+            long aSize = ValueFormatUtils.ParseFileSize(model.GetValue(a, 8).ToString());
+            long bSize = ValueFormatUtils.ParseFileSize(model.GetValue(b, 8).ToString());
+
+            return aSize.CompareTo(bSize);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Helper/ThemeHelper.cs b/src/Ryujinx/UI/Helper/ThemeHelper.cs
new file mode 100644
index 00000000..e1fed1c4
--- /dev/null
+++ b/src/Ryujinx/UI/Helper/ThemeHelper.cs
@@ -0,0 +1,36 @@
+using Gtk;
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.UI.Common.Configuration;
+using System.IO;
+
+namespace Ryujinx.UI.Helper
+{
+    static class ThemeHelper
+    {
+        public static void ApplyTheme()
+        {
+            if (!ConfigurationState.Instance.UI.EnableCustomTheme)
+            {
+                return;
+            }
+
+            if (File.Exists(ConfigurationState.Instance.UI.CustomThemePath) && (Path.GetExtension(ConfigurationState.Instance.UI.CustomThemePath) == ".css"))
+            {
+                CssProvider cssProvider = new();
+
+                cssProvider.LoadFromPath(ConfigurationState.Instance.UI.CustomThemePath);
+
+                StyleContext.AddProviderForScreen(Gdk.Screen.Default, cssProvider, 800);
+            }
+            else
+            {
+                Logger.Warning?.Print(LogClass.Application, $"The \"custom_theme_path\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid path: \"{ConfigurationState.Instance.UI.CustomThemePath}\".");
+
+                ConfigurationState.Instance.UI.CustomThemePath.Value = "";
+                ConfigurationState.Instance.UI.EnableCustomTheme.Value = false;
+                ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/MainWindow.cs b/src/Ryujinx/UI/MainWindow.cs
new file mode 100644
index 00000000..2908f1a8
--- /dev/null
+++ b/src/Ryujinx/UI/MainWindow.cs
@@ -0,0 +1,1941 @@
+using Gtk;
+using LibHac.Common;
+using LibHac.Common.Keys;
+using LibHac.Ncm;
+using LibHac.Ns;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Audio.Backends.Dummy;
+using Ryujinx.Audio.Backends.OpenAL;
+using Ryujinx.Audio.Backends.SDL2;
+using Ryujinx.Audio.Backends.SoundIo;
+using Ryujinx.Audio.Integration;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Multiplayer;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.SystemInterop;
+using Ryujinx.Cpu;
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.GAL.Multithreading;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS;
+using Ryujinx.HLE.HOS.Services.Account.Acc;
+using Ryujinx.HLE.HOS.SystemState;
+using Ryujinx.Input.GTK3;
+using Ryujinx.Input.HLE;
+using Ryujinx.Input.SDL2;
+using Ryujinx.Modules;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Applet;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Helper;
+using Ryujinx.UI.Widgets;
+using Ryujinx.UI.Windows;
+using Silk.NET.Vulkan;
+using SPB.Graphics.Vulkan;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using GUI = Gtk.Builder.ObjectAttribute;
+using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
+
+namespace Ryujinx.UI
+{
+    public class MainWindow : Window
+    {
+        private readonly VirtualFileSystem _virtualFileSystem;
+        private readonly ContentManager _contentManager;
+        private readonly AccountManager _accountManager;
+        private readonly LibHacHorizonManager _libHacHorizonManager;
+
+        private UserChannelPersistence _userChannelPersistence;
+
+        private HLE.Switch _emulationContext;
+
+        private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
+
+        private readonly ApplicationLibrary _applicationLibrary;
+        private readonly GtkHostUIHandler _uiHandler;
+        private readonly AutoResetEvent _deviceExitStatus;
+        private readonly ListStore _tableStore;
+
+        private bool _updatingGameTable;
+        private bool _gameLoaded;
+        private bool _ending;
+
+        private string _currentEmulatedGamePath = null;
+
+        private string _lastScannedAmiiboId = "";
+        private bool _lastScannedAmiiboShowAll = false;
+
+        public RendererWidgetBase RendererWidget;
+        public InputManager InputManager;
+
+        public bool IsFocused;
+
+#pragma warning disable CS0169, CS0649, IDE0044, IDE0051 // Field is never assigned to, Add readonly modifier, Remove unused private member
+
+        [GUI] public MenuItem ExitMenuItem;
+        [GUI] public MenuItem UpdateMenuItem;
+        [GUI] MenuBar _menuBar;
+        [GUI] Box _footerBox;
+        [GUI] Box _statusBar;
+        [GUI] MenuItem _optionMenu;
+        [GUI] MenuItem _manageUserProfiles;
+        [GUI] MenuItem _fileMenu;
+        [GUI] MenuItem _loadApplicationFile;
+        [GUI] MenuItem _loadApplicationFolder;
+        [GUI] MenuItem _appletMenu;
+        [GUI] MenuItem _actionMenu;
+        [GUI] MenuItem _pauseEmulation;
+        [GUI] MenuItem _resumeEmulation;
+        [GUI] MenuItem _stopEmulation;
+        [GUI] MenuItem _simulateWakeUpMessage;
+        [GUI] MenuItem _scanAmiibo;
+        [GUI] MenuItem _takeScreenshot;
+        [GUI] MenuItem _hideUI;
+        [GUI] MenuItem _fullScreen;
+        [GUI] CheckMenuItem _startFullScreen;
+        [GUI] CheckMenuItem _showConsole;
+        [GUI] CheckMenuItem _favToggle;
+        [GUI] MenuItem _firmwareInstallDirectory;
+        [GUI] MenuItem _firmwareInstallFile;
+        [GUI] MenuItem _fileTypesSubMenu;
+        [GUI] Label _fifoStatus;
+        [GUI] CheckMenuItem _iconToggle;
+        [GUI] CheckMenuItem _developerToggle;
+        [GUI] CheckMenuItem _appToggle;
+        [GUI] CheckMenuItem _timePlayedToggle;
+        [GUI] CheckMenuItem _versionToggle;
+        [GUI] CheckMenuItem _lastPlayedToggle;
+        [GUI] CheckMenuItem _fileExtToggle;
+        [GUI] CheckMenuItem _pathToggle;
+        [GUI] CheckMenuItem _fileSizeToggle;
+        [GUI] CheckMenuItem _nspShown;
+        [GUI] CheckMenuItem _pfs0Shown;
+        [GUI] CheckMenuItem _xciShown;
+        [GUI] CheckMenuItem _ncaShown;
+        [GUI] CheckMenuItem _nroShown;
+        [GUI] CheckMenuItem _nsoShown;
+        [GUI] Label _gpuBackend;
+        [GUI] Label _dockedMode;
+        [GUI] Label _aspectRatio;
+        [GUI] Label _gameStatus;
+        [GUI] TreeView _gameTable;
+        [GUI] TreeSelection _gameTableSelection;
+        [GUI] ScrolledWindow _gameTableWindow;
+        [GUI] Label _gpuName;
+        [GUI] Label _progressLabel;
+        [GUI] Label _firmwareVersionLabel;
+        [GUI] Gtk.ProgressBar _progressBar;
+        [GUI] Box _viewBox;
+        [GUI] Label _vSyncStatus;
+        [GUI] Label _volumeStatus;
+        [GUI] Box _listStatusBox;
+        [GUI] Label _loadingStatusLabel;
+        [GUI] Gtk.ProgressBar _loadingStatusBar;
+
+#pragma warning restore CS0649, IDE0044, CS0169, IDE0051
+
+        public MainWindow() : this(new Builder("Ryujinx.UI.MainWindow.glade")) { }
+
+        private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("_mainWin"))
+        {
+            builder.Autoconnect(this);
+
+            // Apply custom theme if needed.
+            ThemeHelper.ApplyTheme();
+
+            SetWindowSizePosition();
+
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+            Title = $"Ryujinx {Program.Version}";
+
+            // Hide emulation context status bar.
+            _statusBar.Hide();
+
+            // Instantiate HLE objects.
+            _virtualFileSystem = VirtualFileSystem.CreateInstance();
+            _libHacHorizonManager = new LibHacHorizonManager();
+
+            _libHacHorizonManager.InitializeFsServer(_virtualFileSystem);
+            _libHacHorizonManager.InitializeArpServer();
+            _libHacHorizonManager.InitializeBcatServer();
+            _libHacHorizonManager.InitializeSystemClients();
+
+            // Save data created before we supported extra data in directory save data will not work properly if
+            // given empty extra data. Luckily some of that extra data can be created using the data from the
+            // save data indexer, which should be enough to check access permissions for user saves.
+            // Every single save data's extra data will be checked and fixed if needed each time the emulator is opened.
+            // Consider removing this at some point in the future when we don't need to worry about old saves.
+            VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient);
+
+            _contentManager = new ContentManager(_virtualFileSystem);
+            _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, CommandLineState.Profile);
+            _userChannelPersistence = new UserChannelPersistence();
+
+            // Instantiate GUI objects.
+            _applicationLibrary = new ApplicationLibrary(_virtualFileSystem);
+            _uiHandler = new GtkHostUIHandler(this);
+            _deviceExitStatus = new AutoResetEvent(false);
+
+            WindowStateEvent += WindowStateEvent_Changed;
+            DeleteEvent += Window_Close;
+            FocusInEvent += MainWindow_FocusInEvent;
+            FocusOutEvent += MainWindow_FocusOutEvent;
+
+            _applicationLibrary.ApplicationAdded += Application_Added;
+            _applicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
+
+            _fileMenu.StateChanged += FileMenu_StateChanged;
+            _actionMenu.StateChanged += ActionMenu_StateChanged;
+            _optionMenu.StateChanged += OptionMenu_StateChanged;
+
+            _gameTable.ButtonReleaseEvent += Row_Clicked;
+            _fullScreen.Activated += FullScreen_Toggled;
+
+            RendererWidgetBase.StatusUpdatedEvent += Update_StatusBar;
+
+            ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
+            ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
+            ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
+            ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
+
+            ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerMode;
+            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateMultiplayerLanInterfaceId;
+
+            if (ConfigurationState.Instance.UI.StartFullscreen)
+            {
+                _startFullScreen.Active = true;
+            }
+
+            _showConsole.Active = ConfigurationState.Instance.UI.ShowConsole.Value;
+            _showConsole.Visible = ConsoleHelper.SetConsoleWindowStateSupported;
+
+            _actionMenu.Sensitive = false;
+            _pauseEmulation.Sensitive = false;
+            _resumeEmulation.Sensitive = false;
+
+            _nspShown.Active = ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value;
+            _pfs0Shown.Active = ConfigurationState.Instance.UI.ShownFileTypes.PFS0.Value;
+            _xciShown.Active = ConfigurationState.Instance.UI.ShownFileTypes.XCI.Value;
+            _ncaShown.Active = ConfigurationState.Instance.UI.ShownFileTypes.NCA.Value;
+            _nroShown.Active = ConfigurationState.Instance.UI.ShownFileTypes.NRO.Value;
+            _nsoShown.Active = ConfigurationState.Instance.UI.ShownFileTypes.NSO.Value;
+
+            _nspShown.Toggled += NSP_Shown_Toggled;
+            _pfs0Shown.Toggled += PFS0_Shown_Toggled;
+            _xciShown.Toggled += XCI_Shown_Toggled;
+            _ncaShown.Toggled += NCA_Shown_Toggled;
+            _nroShown.Toggled += NRO_Shown_Toggled;
+            _nsoShown.Toggled += NSO_Shown_Toggled;
+
+            _fileTypesSubMenu.Visible = FileAssociationHelper.IsTypeAssociationSupported;
+
+            if (ConfigurationState.Instance.UI.GuiColumns.FavColumn)
+            {
+                _favToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.IconColumn)
+            {
+                _iconToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.AppColumn)
+            {
+                _appToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.DevColumn)
+            {
+                _developerToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.VersionColumn)
+            {
+                _versionToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.TimePlayedColumn)
+            {
+                _timePlayedToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.LastPlayedColumn)
+            {
+                _lastPlayedToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.FileExtColumn)
+            {
+                _fileExtToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.FileSizeColumn)
+            {
+                _fileSizeToggle.Active = true;
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.PathColumn)
+            {
+                _pathToggle.Active = true;
+            }
+
+            _favToggle.Toggled += Fav_Toggled;
+            _iconToggle.Toggled += Icon_Toggled;
+            _appToggle.Toggled += App_Toggled;
+            _developerToggle.Toggled += Developer_Toggled;
+            _versionToggle.Toggled += Version_Toggled;
+            _timePlayedToggle.Toggled += TimePlayed_Toggled;
+            _lastPlayedToggle.Toggled += LastPlayed_Toggled;
+            _fileExtToggle.Toggled += FileExt_Toggled;
+            _fileSizeToggle.Toggled += FileSize_Toggled;
+            _pathToggle.Toggled += Path_Toggled;
+
+            _gameTable.Model = _tableStore = new ListStore(
+                typeof(bool),
+                typeof(Gdk.Pixbuf),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(string),
+                typeof(BlitStruct<ApplicationControlProperty>));
+
+            _tableStore.SetSortFunc(5, SortHelper.TimePlayedSort);
+            _tableStore.SetSortFunc(6, SortHelper.LastPlayedSort);
+            _tableStore.SetSortFunc(8, SortHelper.FileSizeSort);
+
+            int columnId = ConfigurationState.Instance.UI.ColumnSort.SortColumnId;
+            bool ascending = ConfigurationState.Instance.UI.ColumnSort.SortAscending;
+
+            _tableStore.SetSortColumnId(columnId, ascending ? SortType.Ascending : SortType.Descending);
+
+            _gameTable.EnableSearch = true;
+            _gameTable.SearchColumn = 2;
+            _gameTable.SearchEqualFunc = (model, col, key, iter) => !((string)model.GetValue(iter, col)).Contains(key, StringComparison.InvariantCultureIgnoreCase);
+
+            _hideUI.Label = _hideUI.Label.Replace("SHOWUIKEY", ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI.ToString());
+
+            UpdateColumns();
+            UpdateGameTable();
+
+            ConfigurationState.Instance.UI.GameDirs.Event += (sender, args) =>
+            {
+                if (args.OldValue != args.NewValue)
+                {
+                    UpdateGameTable();
+                }
+            };
+
+            Task.Run(RefreshFirmwareLabel);
+
+            InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver());
+        }
+
+        private void UpdateMultiplayerLanInterfaceId(object sender, ReactiveEventArgs<string> args)
+        {
+            if (_emulationContext != null)
+            {
+                _emulationContext.Configuration.MultiplayerLanInterfaceId = args.NewValue;
+            }
+        }
+
+        private void UpdateMultiplayerMode(object sender, ReactiveEventArgs<MultiplayerMode> args)
+        {
+            if (_emulationContext != null)
+            {
+                _emulationContext.Configuration.MultiplayerMode = args.NewValue;
+            }
+        }
+
+        private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
+        {
+            if (_emulationContext != null)
+            {
+                _emulationContext.Configuration.IgnoreMissingServices = args.NewValue;
+            }
+        }
+
+        private void UpdateAspectRatioState(object sender, ReactiveEventArgs<AspectRatio> args)
+        {
+            if (_emulationContext != null)
+            {
+                _emulationContext.Configuration.AspectRatio = args.NewValue;
+            }
+        }
+
+        private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
+        {
+            _emulationContext?.System.ChangeDockedModeState(e.NewValue);
+        }
+
+        private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
+        {
+            _emulationContext?.SetVolume(e.NewValue);
+        }
+
+        private void WindowStateEvent_Changed(object o, WindowStateEventArgs args)
+        {
+            _fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen";
+        }
+
+        private void MainWindow_FocusOutEvent(object o, FocusOutEventArgs args)
+        {
+            IsFocused = false;
+        }
+
+        private void MainWindow_FocusInEvent(object o, FocusInEventArgs args)
+        {
+            IsFocused = true;
+        }
+
+        private void UpdateColumns()
+        {
+            foreach (TreeViewColumn column in _gameTable.Columns)
+            {
+                _gameTable.RemoveColumn(column);
+            }
+
+            CellRendererToggle favToggle = new();
+            favToggle.Toggled += FavToggle_Toggled;
+
+            if (ConfigurationState.Instance.UI.GuiColumns.FavColumn)
+            {
+                _gameTable.AppendColumn("Fav", favToggle, "active", 0);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.IconColumn)
+            {
+                _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 1);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.AppColumn)
+            {
+                _gameTable.AppendColumn("Application", new CellRendererText(), "text", 2);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.DevColumn)
+            {
+                _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 3);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.VersionColumn)
+            {
+                _gameTable.AppendColumn("Version", new CellRendererText(), "text", 4);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.TimePlayedColumn)
+            {
+                _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 5);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.LastPlayedColumn)
+            {
+                _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 6);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.FileExtColumn)
+            {
+                _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 7);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.FileSizeColumn)
+            {
+                _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 8);
+            }
+            if (ConfigurationState.Instance.UI.GuiColumns.PathColumn)
+            {
+                _gameTable.AppendColumn("Path", new CellRendererText(), "text", 9);
+            }
+
+            foreach (TreeViewColumn column in _gameTable.Columns)
+            {
+                switch (column.Title)
+                {
+                    case "Fav":
+                        column.SortColumnId = 0;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Application":
+                        column.SortColumnId = 2;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Developer":
+                        column.SortColumnId = 3;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Version":
+                        column.SortColumnId = 4;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Time Played":
+                        column.SortColumnId = 5;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Last Played":
+                        column.SortColumnId = 6;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "File Ext":
+                        column.SortColumnId = 7;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "File Size":
+                        column.SortColumnId = 8;
+                        column.Clicked += Column_Clicked;
+                        break;
+                    case "Path":
+                        column.SortColumnId = 9;
+                        column.Clicked += Column_Clicked;
+                        break;
+                }
+            }
+        }
+
+        protected override void OnDestroyed()
+        {
+            InputManager.Dispose();
+        }
+
+        private void InitializeSwitchInstance()
+        {
+            _virtualFileSystem.ReloadKeySet();
+
+            IRenderer renderer;
+
+            if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
+            {
+                string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
+                renderer = new Graphics.Vulkan.VulkanRenderer(Vk.GetApi(), CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
+            }
+            else
+            {
+                renderer = new Graphics.OpenGL.OpenGLRenderer();
+            }
+
+            BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
+
+            bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
+
+            if (threadedGAL)
+            {
+                renderer = new ThreadedRenderer(renderer);
+            }
+
+            Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {threadedGAL}");
+
+            IHardwareDeviceDriver deviceDriver = new DummyHardwareDeviceDriver();
+
+            if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SDL2)
+            {
+                if (SDL2HardwareDeviceDriver.IsSupported)
+                {
+                    deviceDriver = new SDL2HardwareDeviceDriver();
+                }
+                else
+                {
+                    Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
+
+                    if (OpenALHardwareDeviceDriver.IsSupported)
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
+
+                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
+                        SaveConfig();
+
+                        deviceDriver = new OpenALHardwareDeviceDriver();
+                    }
+                    else
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SoundIO.");
+
+                        if (SoundIoHardwareDeviceDriver.IsSupported)
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
+
+                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
+                            SaveConfig();
+
+                            deviceDriver = new SoundIoHardwareDeviceDriver();
+                        }
+                        else
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
+                        }
+                    }
+                }
+            }
+            else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SoundIo)
+            {
+                if (SoundIoHardwareDeviceDriver.IsSupported)
+                {
+                    deviceDriver = new SoundIoHardwareDeviceDriver();
+                }
+                else
+                {
+                    Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, trying to fall back to SDL2.");
+
+                    if (SDL2HardwareDeviceDriver.IsSupported)
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
+
+                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
+                        SaveConfig();
+
+                        deviceDriver = new SDL2HardwareDeviceDriver();
+                    }
+                    else
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
+
+                        if (OpenALHardwareDeviceDriver.IsSupported)
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
+
+                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
+                            SaveConfig();
+
+                            deviceDriver = new OpenALHardwareDeviceDriver();
+                        }
+                        else
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, falling back to dummy audio out.");
+                        }
+                    }
+                }
+            }
+            else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.OpenAl)
+            {
+                if (OpenALHardwareDeviceDriver.IsSupported)
+                {
+                    deviceDriver = new OpenALHardwareDeviceDriver();
+                }
+                else
+                {
+                    Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SDL2.");
+
+                    if (SDL2HardwareDeviceDriver.IsSupported)
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
+
+                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
+                        SaveConfig();
+
+                        deviceDriver = new SDL2HardwareDeviceDriver();
+                    }
+                    else
+                    {
+                        Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to SoundIO.");
+
+                        if (SoundIoHardwareDeviceDriver.IsSupported)
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
+
+                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
+                            SaveConfig();
+
+                            deviceDriver = new SoundIoHardwareDeviceDriver();
+                        }
+                        else
+                        {
+                            Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
+                        }
+                    }
+                }
+            }
+
+            var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value
+                ? HLE.MemoryConfiguration.MemoryConfiguration6GiB
+                : HLE.MemoryConfiguration.MemoryConfiguration4GiB;
+
+            IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None;
+
+            HLE.HLEConfiguration configuration = new(_virtualFileSystem,
+                _libHacHorizonManager,
+                _contentManager,
+                _accountManager,
+                _userChannelPersistence,
+                renderer,
+                deviceDriver,
+                memoryConfiguration,
+                _uiHandler,
+                (SystemLanguage)ConfigurationState.Instance.System.Language.Value,
+                (RegionCode)ConfigurationState.Instance.System.Region.Value,
+                ConfigurationState.Instance.Graphics.EnableVsync,
+                ConfigurationState.Instance.System.EnableDockedMode,
+                ConfigurationState.Instance.System.EnablePtc,
+                ConfigurationState.Instance.System.EnableInternetAccess,
+                fsIntegrityCheckLevel,
+                ConfigurationState.Instance.System.FsGlobalAccessLogMode,
+                ConfigurationState.Instance.System.SystemTimeOffset,
+                ConfigurationState.Instance.System.TimeZone,
+                ConfigurationState.Instance.System.MemoryManagerMode,
+                ConfigurationState.Instance.System.IgnoreMissingServices,
+                ConfigurationState.Instance.Graphics.AspectRatio,
+                ConfigurationState.Instance.System.AudioVolume,
+                ConfigurationState.Instance.System.UseHypervisor,
+                ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
+                ConfigurationState.Instance.Multiplayer.Mode);
+
+            _emulationContext = new HLE.Switch(configuration);
+        }
+
+        private SurfaceKHR CreateVulkanSurface(Instance instance, Vk vk)
+        {
+            return new SurfaceKHR((ulong)((VulkanRenderer)RendererWidget).CreateWindowSurface(instance.Handle));
+        }
+
+        private void SetupProgressUIHandlers()
+        {
+            if (_emulationContext.Processes.ActiveApplication.DiskCacheLoadState != null)
+            {
+                _emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged -= ProgressHandler;
+                _emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged += ProgressHandler;
+            }
+
+            _emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
+            _emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
+        }
+
+        private void ProgressHandler<T>(T state, int current, int total) where T : Enum
+        {
+            bool visible;
+            string label;
+
+            switch (state)
+            {
+                case LoadState ptcState:
+                    visible = ptcState != LoadState.Loaded;
+                    label = $"PTC : {current}/{total}";
+                    break;
+                case ShaderCacheLoadingState shaderCacheState:
+                    visible = shaderCacheState != ShaderCacheLoadingState.Loaded;
+                    label = $"Shaders : {current}/{total}";
+                    break;
+                default:
+                    throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
+            }
+
+            Application.Invoke(delegate
+            {
+                _loadingStatusLabel.Text = label;
+                _loadingStatusBar.Fraction = total > 0 ? (double)current / total : 0;
+                _loadingStatusBar.Visible = visible;
+                _loadingStatusLabel.Visible = visible;
+            });
+        }
+
+        public void UpdateGameTable()
+        {
+            if (_updatingGameTable || _gameLoaded)
+            {
+                return;
+            }
+
+            _updatingGameTable = true;
+
+            _tableStore.Clear();
+
+            Thread applicationLibraryThread = new(() =>
+            {
+                _applicationLibrary.LoadApplications(ConfigurationState.Instance.UI.GameDirs, ConfigurationState.Instance.System.Language);
+
+                _updatingGameTable = false;
+            })
+            {
+                Name = "GUI.ApplicationLibraryThread",
+                IsBackground = true,
+            };
+            applicationLibraryThread.Start();
+        }
+
+        [Conditional("RELEASE")]
+        public void PerformanceCheck()
+        {
+            if (ConfigurationState.Instance.Logger.EnableTrace.Value)
+            {
+                MessageDialog debugWarningDialog = new(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
+                {
+                    Title = "Ryujinx - Warning",
+                    Text = "You have trace logging enabled, which is designed to be used by developers only.",
+                    SecondaryText = "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?",
+                };
+
+                if (debugWarningDialog.Run() == (int)ResponseType.Yes)
+                {
+                    ConfigurationState.Instance.Logger.EnableTrace.Value = false;
+                    SaveConfig();
+                }
+
+                debugWarningDialog.Dispose();
+            }
+
+            if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value))
+            {
+                MessageDialog shadersDumpWarningDialog = new(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
+                {
+                    Title = "Ryujinx - Warning",
+                    Text = "You have shader dumping enabled, which is designed to be used by developers only.",
+                    SecondaryText = "For optimal performance, it's recommended to disable shader dumping. Would you like to disable shader dumping now?",
+                };
+
+                if (shadersDumpWarningDialog.Run() == (int)ResponseType.Yes)
+                {
+                    ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = "";
+                    SaveConfig();
+                }
+
+                shadersDumpWarningDialog.Dispose();
+            }
+        }
+
+        private bool LoadApplication(string path, bool isFirmwareTitle)
+        {
+            SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
+
+            if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError))
+            {
+                if (SetupValidator.CanFixStartApplication(_contentManager, path, userError, out firmwareVersion))
+                {
+                    string message = $"Would you like to install the firmware embedded in this game? (Firmware {firmwareVersion.VersionString})";
+
+                    ResponseType responseDialog = (ResponseType)GtkDialog.CreateConfirmationDialog("No Firmware Installed", message).Run();
+
+                    if (responseDialog != ResponseType.Yes || !SetupValidator.TryFixStartApplication(_contentManager, path, userError, out _))
+                    {
+                        UserErrorDialog.CreateUserErrorDialog(userError);
+
+                        return false;
+                    }
+
+                    // Tell the user that we installed a firmware for them.
+
+                    firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
+
+                    RefreshFirmwareLabel();
+
+                    message = $"No installed firmware was found but Ryujinx was able to install firmware {firmwareVersion.VersionString} from the provided game.\nThe emulator will now start.";
+
+                    GtkDialog.CreateInfoDialog($"Firmware {firmwareVersion.VersionString} was installed", message);
+                }
+                else
+                {
+                    UserErrorDialog.CreateUserErrorDialog(userError);
+
+                    return false;
+                }
+            }
+
+            Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
+
+            if (isFirmwareTitle)
+            {
+                Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
+
+                return _emulationContext.LoadNca(path);
+            }
+
+            if (Directory.Exists(path))
+            {
+                string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
+
+                if (romFsFiles.Length == 0)
+                {
+                    romFsFiles = Directory.GetFiles(path, "*.romfs");
+                }
+
+                if (romFsFiles.Length > 0)
+                {
+                    Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
+
+                    return _emulationContext.LoadCart(path, romFsFiles[0]);
+                }
+
+                Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS.");
+
+                return _emulationContext.LoadCart(path);
+            }
+
+            if (File.Exists(path))
+            {
+                switch (System.IO.Path.GetExtension(path).ToLowerInvariant())
+                {
+                    case ".xci":
+                        Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
+
+                        return _emulationContext.LoadXci(path);
+                    case ".nca":
+                        Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
+
+                        return _emulationContext.LoadNca(path);
+                    case ".nsp":
+                    case ".pfs0":
+                        Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
+
+                        return _emulationContext.LoadNsp(path);
+                    default:
+                        Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
+                        try
+                        {
+                            return _emulationContext.LoadProgram(path);
+                        }
+                        catch (ArgumentOutOfRangeException)
+                        {
+                            Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");
+
+                            return false;
+                        }
+                }
+            }
+
+            Logger.Warning?.Print(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
+
+            return false;
+        }
+
+        public void RunApplication(string path, bool startFullscreen = false)
+        {
+            if (_gameLoaded)
+            {
+                GtkDialog.CreateInfoDialog("A game has already been loaded", "Please stop emulation or close the emulator before launching another game.");
+            }
+            else
+            {
+                PerformanceCheck();
+
+                Logger.RestartTime();
+
+                RendererWidget = CreateRendererWidget();
+
+                SwitchToRenderWidget(startFullscreen);
+
+                InitializeSwitchInstance();
+
+                UpdateGraphicsConfig();
+
+                bool isFirmwareTitle = false;
+
+                if (path.StartsWith("@SystemContent"))
+                {
+                    path = VirtualFileSystem.SwitchPathToSystemPath(path);
+
+                    isFirmwareTitle = true;
+                }
+
+                if (!LoadApplication(path, isFirmwareTitle))
+                {
+                    _emulationContext.Dispose();
+                    SwitchToGameTable();
+
+                    return;
+                }
+
+                SetupProgressUIHandlers();
+
+                _currentEmulatedGamePath = path;
+
+                _deviceExitStatus.Reset();
+
+                Thread windowThread = new(CreateGameWindow)
+                {
+                    Name = "GUI.WindowThread",
+                };
+
+                windowThread.Start();
+
+                _gameLoaded = true;
+                _actionMenu.Sensitive = true;
+                UpdateMenuItem.Sensitive = false;
+
+                _lastScannedAmiiboId = "";
+
+                _firmwareInstallFile.Sensitive = false;
+                _firmwareInstallDirectory.Sensitive = false;
+
+                DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
+                                                              _emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString());
+
+                ApplicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata =>
+                {
+                    appMetadata.UpdatePreGame();
+                });
+            }
+        }
+
+        private RendererWidgetBase CreateRendererWidget()
+        {
+            if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
+            {
+                return new VulkanRenderer(InputManager, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
+            }
+            else
+            {
+                return new OpenGLRenderer(InputManager, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
+            }
+        }
+
+        private void SwitchToRenderWidget(bool startFullscreen = false)
+        {
+            _viewBox.Remove(_gameTableWindow);
+            RendererWidget.Expand = true;
+            _viewBox.Child = RendererWidget;
+
+            RendererWidget.ShowAll();
+            EditFooterForGameRenderer();
+
+            if (Window.State.HasFlag(Gdk.WindowState.Fullscreen))
+            {
+                ToggleExtraWidgets(false);
+            }
+            else if (startFullscreen || ConfigurationState.Instance.UI.StartFullscreen.Value)
+            {
+                FullScreen_Toggled(null, null);
+            }
+        }
+
+        private void SwitchToGameTable()
+        {
+            if (Window.State.HasFlag(Gdk.WindowState.Fullscreen))
+            {
+                ToggleExtraWidgets(true);
+            }
+
+            RendererWidget.Exit();
+
+            if (RendererWidget.Window != Window && RendererWidget.Window != null)
+            {
+                RendererWidget.Window.Dispose();
+            }
+
+            RendererWidget.Dispose();
+
+            if (OperatingSystem.IsWindows())
+            {
+                _windowsMultimediaTimerResolution?.Dispose();
+                _windowsMultimediaTimerResolution = null;
+            }
+
+            DisplaySleep.Restore();
+
+            _viewBox.Remove(RendererWidget);
+            _viewBox.Add(_gameTableWindow);
+
+            _gameTableWindow.Expand = true;
+
+            Window.Title = $"Ryujinx {Program.Version}";
+
+            _emulationContext = null;
+            _gameLoaded = false;
+            RendererWidget = null;
+
+            DiscordIntegrationModule.SwitchToMainMenu();
+
+            RecreateFooterForMenu();
+
+            UpdateColumns();
+            UpdateGameTable();
+
+            RefreshFirmwareLabel();
+            HandleRelaunch();
+        }
+
+        private void CreateGameWindow()
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
+            }
+
+            DisplaySleep.Prevent();
+
+            RendererWidget.Initialize(_emulationContext);
+
+            RendererWidget.WaitEvent.WaitOne();
+
+            RendererWidget.Start();
+
+            _emulationContext.Dispose();
+            _deviceExitStatus.Set();
+
+            // NOTE: Everything that is here will not be executed when you close the UI.
+            Application.Invoke(delegate
+            {
+                SwitchToGameTable();
+            });
+        }
+
+        private void RecreateFooterForMenu()
+        {
+            _listStatusBox.Show();
+            _statusBar.Hide();
+        }
+
+        private void EditFooterForGameRenderer()
+        {
+            _listStatusBox.Hide();
+            _statusBar.Show();
+        }
+
+        public void ToggleExtraWidgets(bool show)
+        {
+            if (RendererWidget != null)
+            {
+                if (show)
+                {
+                    _menuBar.ShowAll();
+                    _footerBox.Show();
+                    _statusBar.Show();
+                }
+                else
+                {
+                    _menuBar.Hide();
+                    _footerBox.Hide();
+                }
+            }
+        }
+
+        private void UpdateGameMetadata(string titleId)
+        {
+            if (_gameLoaded)
+            {
+                ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
+                {
+                    appMetadata.UpdatePostGame();
+                });
+            }
+        }
+
+        public static void UpdateGraphicsConfig()
+        {
+            int resScale = ConfigurationState.Instance.Graphics.ResScale;
+            float resScaleCustom = ConfigurationState.Instance.Graphics.ResScaleCustom;
+
+            Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale;
+            Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
+            Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
+            Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
+            Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
+            Graphics.Gpu.GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
+        }
+
+        public void UpdateInternetAccess()
+        {
+            if (_gameLoaded)
+            {
+                _emulationContext.Configuration.EnableInternetAccess = ConfigurationState.Instance.System.EnableInternetAccess.Value;
+            }
+        }
+
+        public static void SaveConfig()
+        {
+            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+        }
+
+        private void End()
+        {
+            if (_ending)
+            {
+                return;
+            }
+
+            _ending = true;
+
+            if (_emulationContext != null)
+            {
+                UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
+
+                if (RendererWidget != null)
+                {
+                    // We tell the widget that we are exiting.
+                    RendererWidget.Exit();
+
+                    // Wait for the other thread to dispose the HLE context before exiting.
+                    _deviceExitStatus.WaitOne();
+                    RendererWidget.Dispose();
+                }
+            }
+
+            Dispose();
+
+            Program.Exit();
+            Application.Quit();
+        }
+
+        //
+        // Events
+        //
+        private void Application_Added(object sender, ApplicationAddedEventArgs args)
+        {
+            Application.Invoke(delegate
+            {
+                _tableStore.AppendValues(
+                    args.AppData.Favorite,
+                    new Gdk.Pixbuf(args.AppData.Icon, 75, 75),
+                    $"{args.AppData.TitleName}\n{args.AppData.TitleId.ToUpper()}",
+                    args.AppData.Developer,
+                    args.AppData.Version,
+                    args.AppData.TimePlayedString,
+                    args.AppData.LastPlayedString,
+                    args.AppData.FileExtension,
+                    args.AppData.FileSizeString,
+                    args.AppData.Path,
+                    args.AppData.ControlHolder);
+            });
+        }
+
+        private void ApplicationCount_Updated(object sender, ApplicationCountUpdatedEventArgs args)
+        {
+            Application.Invoke(delegate
+            {
+                _progressLabel.Text = $"{args.NumAppsLoaded}/{args.NumAppsFound} Games Loaded";
+                float barValue = 0;
+
+                if (args.NumAppsFound != 0)
+                {
+                    barValue = (float)args.NumAppsLoaded / args.NumAppsFound;
+                }
+
+                _progressBar.Fraction = barValue;
+
+                // Reset the vertical scrollbar to the top when titles finish loading
+                if (args.NumAppsLoaded == args.NumAppsFound)
+                {
+                    _gameTableWindow.Vadjustment.Value = 0;
+                }
+            });
+        }
+
+        private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
+        {
+            Application.Invoke(delegate
+            {
+                _gameStatus.Text = args.GameStatus;
+                _fifoStatus.Text = args.FifoStatus;
+                _gpuName.Text = args.GpuName;
+                _dockedMode.Text = args.DockedMode;
+                _aspectRatio.Text = args.AspectRatio;
+                _gpuBackend.Text = args.GpuBackend;
+                _volumeStatus.Text = GetVolumeLabelText(args.Volume);
+
+                if (args.VSyncEnabled)
+                {
+                    _vSyncStatus.Attributes = new Pango.AttrList();
+                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(11822, 60138, 51657));
+                }
+                else
+                {
+                    _vSyncStatus.Attributes = new Pango.AttrList();
+                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(ushort.MaxValue, 17733, 21588));
+                }
+            });
+        }
+
+        private void FavToggle_Toggled(object sender, ToggledArgs args)
+        {
+            _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path));
+
+            string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
+            bool newToggleValue = !(bool)_tableStore.GetValue(treeIter, 0);
+
+            _tableStore.SetValue(treeIter, 0, newToggleValue);
+
+            ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
+            {
+                appMetadata.Favorite = newToggleValue;
+            });
+        }
+
+        private void Column_Clicked(object sender, EventArgs args)
+        {
+            TreeViewColumn column = (TreeViewColumn)sender;
+
+            ConfigurationState.Instance.UI.ColumnSort.SortColumnId.Value = column.SortColumnId;
+            ConfigurationState.Instance.UI.ColumnSort.SortAscending.Value = column.SortOrder == SortType.Ascending;
+
+            SaveConfig();
+        }
+
+        private void Row_Activated(object sender, RowActivatedArgs args)
+        {
+            _gameTableSelection.GetSelected(out TreeIter treeIter);
+
+            string path = (string)_tableStore.GetValue(treeIter, 9);
+
+            RunApplication(path);
+        }
+
+        private void VSyncStatus_Clicked(object sender, ButtonReleaseEventArgs args)
+        {
+            _emulationContext.EnableDeviceVsync = !_emulationContext.EnableDeviceVsync;
+
+            Logger.Info?.Print(LogClass.Application, $"VSync toggled to: {_emulationContext.EnableDeviceVsync}");
+        }
+
+        private void DockedMode_Clicked(object sender, ButtonReleaseEventArgs args)
+        {
+            ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
+        }
+
+        private static string GetVolumeLabelText(float volume)
+        {
+            string icon = volume == 0 ? "🔇" : "🔊";
+
+            return $"{icon} {(int)(volume * 100)}%";
+        }
+
+        private void VolumeStatus_Clicked(object sender, ButtonReleaseEventArgs args)
+        {
+            if (_emulationContext != null)
+            {
+                if (_emulationContext.IsAudioMuted())
+                {
+                    _emulationContext.SetVolume(ConfigurationState.Instance.System.AudioVolume);
+                }
+                else
+                {
+                    _emulationContext.SetVolume(0);
+                }
+            }
+        }
+
+        private void AspectRatio_Clicked(object sender, ButtonReleaseEventArgs args)
+        {
+            AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
+
+            ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames<AspectRatio>().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
+        }
+
+        private void Row_Clicked(object sender, ButtonReleaseEventArgs args)
+        {
+            if (args.Event.Button != 3 /* Right Click */)
+            {
+                return;
+            }
+
+            _gameTableSelection.GetSelected(out TreeIter treeIter);
+
+            if (treeIter.UserData == IntPtr.Zero)
+            {
+                return;
+            }
+
+            string titleFilePath = _tableStore.GetValue(treeIter, 9).ToString();
+            string titleName = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[0];
+            string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
+
+            BlitStruct<ApplicationControlProperty> controlData = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10);
+
+            _ = new GameTableContextMenu(this, _virtualFileSystem, _accountManager, _libHacHorizonManager.RyujinxClient, titleFilePath, titleName, titleId, controlData);
+        }
+
+        private void Load_Application_File(object sender, EventArgs args)
+        {
+            using FileChooserNative fileChooser = new("Choose the file to open", this, FileChooserAction.Open, "Open", "Cancel");
+
+            FileFilter filter = new()
+            {
+                Name = "Switch Executables",
+            };
+            filter.AddPattern("*.xci");
+            filter.AddPattern("*.nsp");
+            filter.AddPattern("*.pfs0");
+            filter.AddPattern("*.nca");
+            filter.AddPattern("*.nro");
+            filter.AddPattern("*.nso");
+
+            fileChooser.AddFilter(filter);
+
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                RunApplication(fileChooser.Filename);
+            }
+        }
+
+        private void Load_Application_Folder(object sender, EventArgs args)
+        {
+            using FileChooserNative fileChooser = new("Choose the folder to open", this, FileChooserAction.SelectFolder, "Open", "Cancel");
+
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                RunApplication(fileChooser.Filename);
+            }
+        }
+
+        private void FileMenu_StateChanged(object o, StateChangedArgs args)
+        {
+            _appletMenu.Sensitive = _emulationContext == null && _contentManager.GetCurrentFirmwareVersion() != null && _contentManager.GetCurrentFirmwareVersion().Major > 3;
+            _loadApplicationFile.Sensitive = _emulationContext == null;
+            _loadApplicationFolder.Sensitive = _emulationContext == null;
+        }
+
+        private void Load_Mii_Edit_Applet(object sender, EventArgs args)
+        {
+            string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
+
+            RunApplication(contentPath);
+        }
+
+        private void Open_Ryu_Folder(object sender, EventArgs args)
+        {
+            OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
+        }
+
+        private void OpenLogsFolder_Pressed(object sender, EventArgs args)
+        {
+            string logPath = AppDataManager.GetOrCreateLogsDir();
+            if (!string.IsNullOrEmpty(logPath))
+            {
+                OpenHelper.OpenFolder(logPath);
+            }
+        }
+
+        private void Exit_Pressed(object sender, EventArgs args)
+        {
+            if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
+            {
+                SaveWindowSizePosition();
+                End();
+            }
+        }
+
+        private void Window_Close(object sender, DeleteEventArgs args)
+        {
+            if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
+            {
+                SaveWindowSizePosition();
+                End();
+            }
+            else
+            {
+                args.RetVal = true;
+            }
+        }
+
+        private void SetWindowSizePosition()
+        {
+            DefaultWidth = ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth;
+            DefaultHeight = ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight;
+
+            Move(ConfigurationState.Instance.UI.WindowStartup.WindowPositionX, ConfigurationState.Instance.UI.WindowStartup.WindowPositionY);
+
+            if (ConfigurationState.Instance.UI.WindowStartup.WindowMaximized)
+            {
+                Maximize();
+            }
+        }
+
+        private void SaveWindowSizePosition()
+        {
+            GetSize(out int windowWidth, out int windowHeight);
+            GetPosition(out int windowXPos, out int windowYPos);
+
+            ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = IsMaximized;
+            ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth.Value = windowWidth;
+            ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight.Value = windowHeight;
+            ConfigurationState.Instance.UI.WindowStartup.WindowPositionX.Value = windowXPos;
+            ConfigurationState.Instance.UI.WindowStartup.WindowPositionY.Value = windowYPos;
+
+            SaveConfig();
+        }
+
+        private void StopEmulation_Pressed(object sender, EventArgs args)
+        {
+            if (_emulationContext != null)
+            {
+                UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
+            }
+
+            _pauseEmulation.Sensitive = false;
+            _resumeEmulation.Sensitive = false;
+            UpdateMenuItem.Sensitive = true;
+            RendererWidget?.Exit();
+        }
+
+        private void PauseEmulation_Pressed(object sender, EventArgs args)
+        {
+            _pauseEmulation.Sensitive = false;
+            _resumeEmulation.Sensitive = true;
+            _emulationContext.System.TogglePauseEmulation(true);
+            Title = TitleHelper.ActiveApplicationTitle(_emulationContext.Processes.ActiveApplication, Program.Version, "Paused");
+            Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
+        }
+
+        private void ResumeEmulation_Pressed(object sender, EventArgs args)
+        {
+            _pauseEmulation.Sensitive = true;
+            _resumeEmulation.Sensitive = false;
+            _emulationContext.System.TogglePauseEmulation(false);
+            Title = TitleHelper.ActiveApplicationTitle(_emulationContext.Processes.ActiveApplication, Program.Version);
+            Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
+        }
+
+        public void ActivatePauseMenu()
+        {
+            _pauseEmulation.Sensitive = true;
+            _resumeEmulation.Sensitive = false;
+        }
+
+        public void TogglePause()
+        {
+            _pauseEmulation.Sensitive ^= true;
+            _resumeEmulation.Sensitive ^= true;
+            _emulationContext.System.TogglePauseEmulation(_resumeEmulation.Sensitive);
+        }
+
+        private void Installer_File_Pressed(object o, EventArgs args)
+        {
+            FileChooserNative fileChooser = new("Choose the firmware file to open", this, FileChooserAction.Open, "Open", "Cancel");
+
+            FileFilter filter = new()
+            {
+                Name = "Switch Firmware Files",
+            };
+            filter.AddPattern("*.zip");
+            filter.AddPattern("*.xci");
+
+            fileChooser.AddFilter(filter);
+
+            HandleInstallerDialog(fileChooser);
+        }
+
+        private void Installer_Directory_Pressed(object o, EventArgs args)
+        {
+            FileChooserNative directoryChooser = new("Choose the firmware directory to open", this, FileChooserAction.SelectFolder, "Open", "Cancel");
+
+            HandleInstallerDialog(directoryChooser);
+        }
+
+        private void HandleInstallerDialog(FileChooserNative fileChooser)
+        {
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                try
+                {
+                    string filename = fileChooser.Filename;
+
+                    fileChooser.Dispose();
+
+                    SystemVersion firmwareVersion = _contentManager.VerifyFirmwarePackage(filename);
+
+                    if (firmwareVersion is null)
+                    {
+                        GtkDialog.CreateErrorDialog($"A valid system firmware was not found in {filename}.");
+
+                        return;
+                    }
+
+                    string dialogTitle = $"Install Firmware {firmwareVersion.VersionString}";
+
+                    SystemVersion currentVersion = _contentManager.GetCurrentFirmwareVersion();
+
+                    string dialogMessage = $"System version {firmwareVersion.VersionString} will be installed.";
+
+                    if (currentVersion != null)
+                    {
+                        dialogMessage += $"\n\nThis will replace the current system version {currentVersion.VersionString}. ";
+                    }
+
+                    dialogMessage += "\n\nDo you want to continue?";
+
+                    ResponseType responseInstallDialog = (ResponseType)GtkDialog.CreateConfirmationDialog(dialogTitle, dialogMessage).Run();
+
+                    MessageDialog waitingDialog = GtkDialog.CreateWaitingDialog(dialogTitle, "Installing firmware...");
+
+                    if (responseInstallDialog == ResponseType.Yes)
+                    {
+                        Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
+
+                        Thread thread = new(() =>
+                        {
+                            Application.Invoke(delegate
+                            {
+                                waitingDialog.Run();
+
+                            });
+
+                            try
+                            {
+                                _contentManager.InstallFirmware(filename);
+
+                                Application.Invoke(delegate
+                                {
+                                    waitingDialog.Dispose();
+
+                                    string message = $"System version {firmwareVersion.VersionString} successfully installed.";
+
+                                    GtkDialog.CreateInfoDialog(dialogTitle, message);
+                                    Logger.Info?.Print(LogClass.Application, message);
+
+                                    // Purge Applet Cache.
+
+                                    DirectoryInfo miiEditorCacheFolder = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
+
+                                    if (miiEditorCacheFolder.Exists)
+                                    {
+                                        miiEditorCacheFolder.Delete(true);
+                                    }
+                                });
+                            }
+                            catch (Exception ex)
+                            {
+                                Application.Invoke(delegate
+                                {
+                                    waitingDialog.Dispose();
+
+                                    GtkDialog.CreateErrorDialog(ex.Message);
+                                });
+                            }
+                            finally
+                            {
+                                RefreshFirmwareLabel();
+                            }
+                        })
+                        {
+                            Name = "GUI.FirmwareInstallerThread",
+                        };
+                        thread.Start();
+                    }
+                }
+                catch (MissingKeyException ex)
+                {
+                    Logger.Error?.Print(LogClass.Application, ex.ToString());
+                    UserErrorDialog.CreateUserErrorDialog(UserError.FirmwareParsingFailed);
+                }
+                catch (Exception ex)
+                {
+                    GtkDialog.CreateErrorDialog(ex.Message);
+                }
+            }
+            else
+            {
+                fileChooser.Dispose();
+            }
+        }
+
+        private void RefreshFirmwareLabel()
+        {
+            SystemVersion currentFirmware = _contentManager.GetCurrentFirmwareVersion();
+
+            Application.Invoke(delegate
+            {
+                _firmwareVersionLabel.Text = currentFirmware != null ? currentFirmware.VersionString : "0.0.0";
+            });
+        }
+
+        private void InstallFileTypes_Pressed(object sender, EventArgs e)
+        {
+            if (FileAssociationHelper.Install())
+            {
+                GtkDialog.CreateInfoDialog("Install file types", "File types successfully installed!");
+            }
+            else
+            {
+                GtkDialog.CreateErrorDialog("Failed to install file types.");
+            }
+        }
+
+        private void UninstallFileTypes_Pressed(object sender, EventArgs e)
+        {
+            if (FileAssociationHelper.Uninstall())
+            {
+                GtkDialog.CreateInfoDialog("Uninstall file types", "File types successfully uninstalled!");
+            }
+            else
+            {
+                GtkDialog.CreateErrorDialog("Failed to uninstall file types.");
+            }
+        }
+
+        private void HandleRelaunch()
+        {
+            if (_userChannelPersistence.PreviousIndex != -1 && _userChannelPersistence.ShouldRestart)
+            {
+                _userChannelPersistence.ShouldRestart = false;
+
+                RunApplication(_currentEmulatedGamePath);
+            }
+            else
+            {
+                // otherwise, clear state.
+                _userChannelPersistence = new UserChannelPersistence();
+                _currentEmulatedGamePath = null;
+                _actionMenu.Sensitive = false;
+                _firmwareInstallFile.Sensitive = true;
+                _firmwareInstallDirectory.Sensitive = true;
+            }
+        }
+
+        private void FullScreen_Toggled(object sender, EventArgs args)
+        {
+            if (!Window.State.HasFlag(Gdk.WindowState.Fullscreen))
+            {
+                Fullscreen();
+
+                ToggleExtraWidgets(false);
+            }
+            else
+            {
+                Unfullscreen();
+
+                ToggleExtraWidgets(true);
+            }
+        }
+
+        private void StartFullScreen_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.StartFullscreen.Value = _startFullScreen.Active;
+
+            SaveConfig();
+        }
+
+        private void ShowConsole_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShowConsole.Value = _showConsole.Active;
+
+            SaveConfig();
+        }
+
+        private void OptionMenu_StateChanged(object o, StateChangedArgs args)
+        {
+            _manageUserProfiles.Sensitive = _emulationContext == null;
+        }
+
+        private void Settings_Pressed(object sender, EventArgs args)
+        {
+            SettingsWindow settingsWindow = new(this, _virtualFileSystem, _contentManager);
+
+            settingsWindow.SetSizeRequest((int)(settingsWindow.DefaultWidth * Program.WindowScaleFactor), (int)(settingsWindow.DefaultHeight * Program.WindowScaleFactor));
+            settingsWindow.Show();
+        }
+
+        private void HideUI_Pressed(object sender, EventArgs args)
+        {
+            ToggleExtraWidgets(false);
+        }
+
+        private void ManageCheats_Pressed(object sender, EventArgs args)
+        {
+            var window = new CheatWindow(
+                _virtualFileSystem,
+                _emulationContext.Processes.ActiveApplication.ProgramId,
+                _emulationContext.Processes.ActiveApplication.ApplicationControlProperties
+                    .Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString(),
+                _currentEmulatedGamePath);
+
+            window.Destroyed += CheatWindow_Destroyed;
+            window.Show();
+        }
+
+        private void CheatWindow_Destroyed(object sender, EventArgs e)
+        {
+            _emulationContext.EnableCheats();
+            (sender as CheatWindow).Destroyed -= CheatWindow_Destroyed;
+        }
+
+        private void ManageUserProfiles_Pressed(object sender, EventArgs args)
+        {
+            UserProfilesManagerWindow userProfilesManagerWindow = new(_accountManager, _contentManager, _virtualFileSystem);
+
+            userProfilesManagerWindow.SetSizeRequest((int)(userProfilesManagerWindow.DefaultWidth * Program.WindowScaleFactor), (int)(userProfilesManagerWindow.DefaultHeight * Program.WindowScaleFactor));
+            userProfilesManagerWindow.Show();
+        }
+
+        private void Simulate_WakeUp_Message_Pressed(object sender, EventArgs args)
+        {
+            _emulationContext?.System.SimulateWakeUpMessage();
+        }
+
+        private void ActionMenu_StateChanged(object o, StateChangedArgs args)
+        {
+            _scanAmiibo.Sensitive = _emulationContext != null && _emulationContext.System.SearchingForAmiibo(out int _);
+            _takeScreenshot.Sensitive = _emulationContext != null;
+        }
+
+        private void Scan_Amiibo(object sender, EventArgs args)
+        {
+            if (_emulationContext.System.SearchingForAmiibo(out int deviceId))
+            {
+                AmiiboWindow amiiboWindow = new()
+                {
+                    LastScannedAmiiboShowAll = _lastScannedAmiiboShowAll,
+                    LastScannedAmiiboId = _lastScannedAmiiboId,
+                    DeviceId = deviceId,
+                    TitleId = _emulationContext.Processes.ActiveApplication.ProgramIdText.ToUpper(),
+                };
+
+                amiiboWindow.DeleteEvent += AmiiboWindow_DeleteEvent;
+
+                amiiboWindow.Show();
+            }
+            else
+            {
+                GtkDialog.CreateInfoDialog($"Amiibo", "The game is currently not ready to receive Amiibo scan data. Ensure that you have an Amiibo-compatible game open and ready to receive Amiibo scan data.");
+            }
+        }
+
+        private void Take_Screenshot(object sender, EventArgs args)
+        {
+            if (_emulationContext != null && RendererWidget != null)
+            {
+                RendererWidget.ScreenshotRequested = true;
+            }
+        }
+
+        private void AmiiboWindow_DeleteEvent(object sender, DeleteEventArgs args)
+        {
+            if (((AmiiboWindow)sender).AmiiboId != "" && ((AmiiboWindow)sender).Response == ResponseType.Ok)
+            {
+                _lastScannedAmiiboId = ((AmiiboWindow)sender).AmiiboId;
+                _lastScannedAmiiboShowAll = ((AmiiboWindow)sender).LastScannedAmiiboShowAll;
+
+                _emulationContext.System.ScanAmiibo(((AmiiboWindow)sender).DeviceId, ((AmiiboWindow)sender).AmiiboId, ((AmiiboWindow)sender).UseRandomUuid);
+            }
+        }
+
+        private void Update_Pressed(object sender, EventArgs args)
+        {
+            if (Updater.CanUpdate(true))
+            {
+                Updater.BeginParse(this, true).ContinueWith(task =>
+                {
+                    Logger.Error?.Print(LogClass.Application, $"Updater error: {task.Exception}");
+                }, TaskContinuationOptions.OnlyOnFaulted);
+            }
+        }
+
+        private void About_Pressed(object sender, EventArgs args)
+        {
+            AboutWindow aboutWindow = new();
+
+            aboutWindow.SetSizeRequest((int)(aboutWindow.DefaultWidth * Program.WindowScaleFactor), (int)(aboutWindow.DefaultHeight * Program.WindowScaleFactor));
+            aboutWindow.Show();
+        }
+
+        private void Fav_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.FavColumn.Value = _favToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void Icon_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.IconColumn.Value = _iconToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void App_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.AppColumn.Value = _appToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void Developer_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.DevColumn.Value = _developerToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void Version_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.VersionColumn.Value = _versionToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void TimePlayed_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.TimePlayedColumn.Value = _timePlayedToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void LastPlayed_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.LastPlayedColumn.Value = _lastPlayedToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void FileExt_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.FileExtColumn.Value = _fileExtToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void FileSize_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.FileSizeColumn.Value = _fileSizeToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void Path_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.GuiColumns.PathColumn.Value = _pathToggle.Active;
+
+            SaveConfig();
+            UpdateColumns();
+        }
+
+        private void NSP_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value = _nspShown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void PFS0_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.PFS0.Value = _pfs0Shown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void XCI_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.XCI.Value = _xciShown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void NCA_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.NCA.Value = _ncaShown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void NRO_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.NRO.Value = _nroShown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void NSO_Shown_Toggled(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.UI.ShownFileTypes.NSO.Value = _nsoShown.Active;
+
+            SaveConfig();
+            UpdateGameTable();
+        }
+
+        private void RefreshList_Pressed(object sender, ButtonReleaseEventArgs args)
+        {
+            UpdateGameTable();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/MainWindow.glade b/src/Ryujinx/UI/MainWindow.glade
new file mode 100644
index 00000000..d1b6872a
--- /dev/null
+++ b/src/Ryujinx/UI/MainWindow.glade
@@ -0,0 +1,1006 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkApplicationWindow" id="_mainWin">
+    <property name="can-focus">False</property>
+    <property name="title" translatable="yes">Ryujinx</property>
+    <property name="window-position">center</property>
+    <child>
+      <object class="GtkBox" id="_box">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkMenuBar" id="_menuBar">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <child>
+              <object class="GtkMenuItem" id="_fileMenu">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">File</property>
+                <property name="use-underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkMenuItem" id="_loadApplicationFile">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open a file explorer to choose a Switch compatible file to load</property>
+                        <property name="label" translatable="yes">Load Application from File</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Load_Application_File" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_loadApplicationFolder">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open a file explorer to choose a Switch compatible, unpacked application to load</property>
+                        <property name="label" translatable="yes">Load Unpacked Game</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Load_Application_Folder" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_appletMenu">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Load Applet</property>
+                        <property name="use-underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkMenuItem" id="LoadMiiEditApplet">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Open Mii Editor Applet in Standalone mode</property>
+                                <property name="label" translatable="yes">Mii Editor</property>
+                                <property name="use-underline">True</property>
+                                <signal name="activate" handler="Load_Mii_Edit_Applet" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="OpenRyuFolder">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open Ryujinx filesystem folder</property>
+                        <property name="label" translatable="yes">Open Ryujinx Folder</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Open_Ryu_Folder" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="OpenLogsFolder">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Opens the folder where logs are written to.</property>
+                        <property name="label" translatable="yes">Open Logs Folder</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="OpenLogsFolder_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="ExitMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Exit Ryujinx</property>
+                        <property name="label" translatable="yes">Exit</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Exit_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="_optionMenu">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Options</property>
+                <property name="use-underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkMenuItem" id="_fullScreen">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Enter Fullscreen</property>
+                        <property name="use-underline">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkCheckMenuItem" id="_startFullScreen">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Start Games in Fullscreen Mode</property>
+                        <property name="use-underline">True</property>
+                        <signal name="toggled" handler="StartFullScreen_Toggled" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkCheckMenuItem" id="_showConsole">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Show Log Console</property>
+                        <property name="use-underline">True</property>
+                        <signal name="toggled" handler="ShowConsole_Toggled" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="GUIColumns">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Select which GUI columns to enable</property>
+                        <property name="label" translatable="yes">Enable GUI Columns</property>
+                        <property name="use-underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_favToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Favorite Games Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Favorite Games Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_iconToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Icon Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Icon Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_appToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Title Name/ID Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Title Name/ID Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_developerToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Developer Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Developer Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_versionToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Version Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Version Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_timePlayedToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Time Played Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Time Played Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_lastPlayedToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Last Played Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Last Played Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_fileExtToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable file extension column in the game list</property>
+                                <property name="label" translatable="yes">Enable File Ext Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_fileSizeToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable File Size Column in the game list</property>
+                                <property name="label" translatable="yes">Enable File Size Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_pathToggle">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Enable or Disable Path Column in the game list</property>
+                                <property name="label" translatable="yes">Enable Path Column</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="ShownFileTypes">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Select which file types to show</property>
+                        <property name="label" translatable="yes">Show File Types</property>
+                        <property name="use-underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_nspShown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .NSP files in the games list</property>
+                                <property name="label" translatable="yes">.NSP</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_pfs0Shown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .PFS0 files in the games list</property>
+                                <property name="label" translatable="yes">.PFS0</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_xciShown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .XCI files in the games list</property>
+                                <property name="label" translatable="yes">.XCI</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_ncaShown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .NCA files in the games list</property>
+                                <property name="label" translatable="yes">.NCA</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_nroShown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .NRO files in the games list</property>
+                                <property name="label" translatable="yes">.NRO</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckMenuItem" id="_nsoShown">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Shows .NSO files in the games list</property>
+                                <property name="label" translatable="yes">.NSO</property>
+                                <property name="use-underline">True</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="SettingsMenu">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open settings window</property>
+                        <property name="label" translatable="yes">Settings</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Settings_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_manageUserProfiles">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open User Profiles Manager window</property>
+                        <property name="label" translatable="yes">Manage User Profiles</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="ManageUserProfiles_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="_actionMenu">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Actions</property>
+                <property name="use-underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkMenuItem" id="_pauseEmulation">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Pause emulation</property>
+                        <property name="label" translatable="yes">Pause Emulation</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="PauseEmulation_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_resumeEmulation">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Resume emulation</property>
+                        <property name="label" translatable="yes">Resume Emulation</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="ResumeEmulation_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_stopEmulation">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Stop emulation of the current game and return to game selection</property>
+                        <property name="label" translatable="yes">Stop Emulation</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="StopEmulation_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_simulateWakeUpMessage">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Simulate a Wake-up Message</property>
+                        <property name="label" translatable="yes">Simulate Wake-up Message</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Simulate_WakeUp_Message_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_scanAmiibo">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Scan an Amiibo</property>
+                        <property name="label" translatable="yes">Scan an Amiibo</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Scan_Amiibo" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_takeScreenshot">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Take a screenshot</property>
+                        <property name="label" translatable="yes">Take Screenshot</property>
+                        <signal name="activate" handler="Take_Screenshot" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_hideUI">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Hide UI (SHOWUIKEY to show)</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="HideUI_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_manageCheats">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Manage Cheats</property>
+                        <signal name="activate" handler="ManageCheats_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="_toolsMenu">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Tools</property>
+                <property name="use-underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkMenuItem" id="FirmwareSubMenu">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Install Firmware</property>
+                        <property name="use-underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkMenuItem" id="_firmwareInstallFile">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="label" translatable="yes">Install a firmware from XCI or ZIP</property>
+                                <property name="use-underline">True</property>
+                                <signal name="activate" handler="Installer_File_Pressed" swapped="no"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkMenuItem" id="_firmwareInstallDirectory">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="label" translatable="yes">Install a firmware from a directory</property>
+                                <property name="use-underline">True</property>
+                                <signal name="activate" handler="Installer_Directory_Pressed" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_fileTypesSubMenu">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Manage file types</property>
+                        <property name="use-underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkMenuItem" id="_installFileTypes">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="label" translatable="yes">Install file types</property>
+                                <signal name="activate" handler="InstallFileTypes_Pressed" swapped="no"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkMenuItem" id="_uninstallFileTypes">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="label" translatable="yes">Uninstall file types</property>
+                                <signal name="activate" handler="UninstallFileTypes_Pressed" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="HelpMenu">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Help</property>
+                <property name="use-underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkMenuItem" id="UpdateMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Check for updates to Ryujinx</property>
+                        <property name="label" translatable="yes">Check for Updates</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="Update_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="About">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="tooltip-text" translatable="yes">Open about window</property>
+                        <property name="label" translatable="yes">About</property>
+                        <property name="use-underline">True</property>
+                        <signal name="activate" handler="About_Pressed" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="_mainBox">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkBox" id="_viewBox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="_gameTableWindow">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="shadow-type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="_gameTable">
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="reorderable">True</property>
+                        <property name="hover-selection">True</property>
+                        <signal name="row-activated" handler="Row_Activated" swapped="no"/>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="_gameTableSelection"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="_footerBox">
+                <property name="height-request">19</property>
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <object class="GtkBox" id="_listStatusBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkEventBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <signal name="button-release-event" handler="RefreshList_Pressed" swapped="no"/>
+                        <child>
+                          <object class="GtkImage">
+                            <property name="name">RefreshList</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="stock">gtk-refresh</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_progressLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">10</property>
+                        <property name="margin-right">5</property>
+                        <property name="margin-top">2</property>
+                        <property name="margin-bottom">2</property>
+                        <property name="label" translatable="yes">0/0 Games Loaded</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkProgressBar" id="_progressBar">
+                        <property name="width-request">200</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin-left">10</property>
+                        <property name="margin-right">5</property>
+                        <property name="margin-bottom">6</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="_statusBar">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkEventBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <signal name="button-release-event" handler="VSyncStatus_Clicked" swapped="no"/>
+                        <child>
+                          <object class="GtkLabel" id="_vSyncStatus">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="label" translatable="yes">VSync</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEventBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <signal name="button-release-event" handler="DockedMode_Clicked" swapped="no"/>
+                        <child>
+                          <object class="GtkLabel" id="_dockedMode">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEventBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <signal name="button-release-event" handler="VolumeStatus_Clicked" swapped="no"/>
+                        <child>
+                          <object class="GtkLabel" id="_volumeStatus">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">5</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEventBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <signal name="button-release-event" handler="AspectRatio_Clicked" swapped="no"/>
+                        <child>
+                          <object class="GtkLabel" id="_aspectRatio">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">6</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">7</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_gameStatus">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">8</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">9</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_fifoStatus">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">10</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">11</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_gpuBackend">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">12</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">13</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_gpuName">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">14</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-left">5</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">System Version</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_firmwareVersionLabel">
+                        <property name="width-request">50</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="pack-type">end</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="pack-type">end</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="_loadingStatusLabel">
+                    <property name="can-focus">False</property>
+                    <property name="margin-left">5</property>
+                    <property name="margin-right">5</property>
+                    <property name="label" translatable="yes">0/0 </property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">11</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkProgressBar" id="_loadingStatusBar">
+                    <property name="width-request">200</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-left">5</property>
+                    <property name="margin-right">5</property>
+                    <property name="margin-bottom">6</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">12</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/OpenGLRenderer.cs b/src/Ryujinx/UI/OpenGLRenderer.cs
new file mode 100644
index 00000000..1fdabc75
--- /dev/null
+++ b/src/Ryujinx/UI/OpenGLRenderer.cs
@@ -0,0 +1,142 @@
+using OpenTK.Graphics.OpenGL;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Input.HLE;
+using SPB.Graphics;
+using SPB.Graphics.Exceptions;
+using SPB.Graphics.OpenGL;
+using SPB.Platform;
+using SPB.Platform.GLX;
+using SPB.Platform.WGL;
+using SPB.Windowing;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.UI
+{
+    public partial class OpenGLRenderer : RendererWidgetBase
+    {
+        private readonly GraphicsDebugLevel _glLogLevel;
+
+        private bool _initializedOpenGL;
+
+        private OpenGLContextBase _openGLContext;
+        private SwappableNativeWindowBase _nativeWindow;
+
+        public OpenGLRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel)
+        {
+            _glLogLevel = glLogLevel;
+        }
+
+        protected override bool OnDrawn(Cairo.Context cr)
+        {
+            if (!_initializedOpenGL)
+            {
+                IntializeOpenGL();
+            }
+
+            return true;
+        }
+
+        private void IntializeOpenGL()
+        {
+            _nativeWindow = RetrieveNativeWindow();
+
+            Window.EnsureNative();
+
+            _openGLContext = PlatformHelper.CreateOpenGLContext(GetGraphicsMode(), 3, 3, _glLogLevel == GraphicsDebugLevel.None ? OpenGLContextFlags.Compat : OpenGLContextFlags.Compat | OpenGLContextFlags.Debug);
+            _openGLContext.Initialize(_nativeWindow);
+            _openGLContext.MakeCurrent(_nativeWindow);
+
+            // Release the GL exclusivity that SPB gave us as we aren't going to use it in GTK Thread.
+            _openGLContext.MakeCurrent(null);
+
+            WaitEvent.Set();
+
+            _initializedOpenGL = true;
+        }
+
+        private SwappableNativeWindowBase RetrieveNativeWindow()
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);
+
+                return new WGLWindow(new NativeHandle(windowHandle));
+            }
+            else if (OperatingSystem.IsLinux())
+            {
+                IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
+                IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
+
+                return new GLXWindow(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
+            }
+
+            throw new NotImplementedException();
+        }
+
+        [LibraryImport("libgdk-3-0.dll")]
+        private static partial IntPtr gdk_win32_window_get_handle(IntPtr d);
+
+        [LibraryImport("libgdk-3.so.0")]
+        private static partial IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
+
+        [LibraryImport("libgdk-3.so.0")]
+        private static partial IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);
+
+        private static FramebufferFormat GetGraphicsMode()
+        {
+            return Environment.OSVersion.Platform == PlatformID.Unix ? new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false) : FramebufferFormat.Default;
+        }
+
+        public override void InitializeRenderer()
+        {
+            // First take exclusivity on the OpenGL context.
+            ((Graphics.OpenGL.OpenGLRenderer)Renderer).InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(_openGLContext));
+
+            _openGLContext.MakeCurrent(_nativeWindow);
+
+            GL.ClearColor(0, 0, 0, 1.0f);
+            GL.Clear(ClearBufferMask.ColorBufferBit);
+            SwapBuffers();
+        }
+
+        public override void SwapBuffers()
+        {
+            _nativeWindow.SwapBuffers();
+        }
+
+        protected override string GetGpuBackendName()
+        {
+            return "OpenGL";
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            // Try to bind the OpenGL context before calling the shutdown event.
+            try
+            {
+                _openGLContext?.MakeCurrent(_nativeWindow);
+            }
+            catch (ContextException e)
+            {
+                Logger.Warning?.Print(LogClass.UI, $"Failed to bind OpenGL context: {e}");
+            }
+
+            Device?.DisposeGpu();
+            NpadManager.Dispose();
+
+            // Unbind context and destroy everything.
+            try
+            {
+                _openGLContext?.MakeCurrent(null);
+            }
+            catch (ContextException e)
+            {
+                Logger.Warning?.Print(LogClass.UI, $"Failed to unbind OpenGL context: {e}");
+            }
+
+            _openGLContext?.Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/OpenToolkitBindingsContext.cs b/src/Ryujinx/UI/OpenToolkitBindingsContext.cs
new file mode 100644
index 00000000..1224ccfe
--- /dev/null
+++ b/src/Ryujinx/UI/OpenToolkitBindingsContext.cs
@@ -0,0 +1,20 @@
+using SPB.Graphics;
+using System;
+
+namespace Ryujinx.UI
+{
+    public class OpenToolkitBindingsContext : OpenTK.IBindingsContext
+    {
+        private readonly IBindingsContext _bindingContext;
+
+        public OpenToolkitBindingsContext(IBindingsContext bindingsContext)
+        {
+            _bindingContext = bindingsContext;
+        }
+
+        public IntPtr GetProcAddress(string procName)
+        {
+            return _bindingContext.GetProcAddress(procName);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/RendererWidgetBase.cs b/src/Ryujinx/UI/RendererWidgetBase.cs
new file mode 100644
index 00000000..e27d0604
--- /dev/null
+++ b/src/Ryujinx/UI/RendererWidgetBase.cs
@@ -0,0 +1,803 @@
+using Gdk;
+using Gtk;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.GAL.Multithreading;
+using Ryujinx.Graphics.Gpu;
+using Ryujinx.Input;
+using Ryujinx.Input.GTK3;
+using Ryujinx.Input.HLE;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Widgets;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Image = SixLabors.ImageSharp.Image;
+using Key = Ryujinx.Input.Key;
+using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
+using Switch = Ryujinx.HLE.Switch;
+
+namespace Ryujinx.UI
+{
+    public abstract class RendererWidgetBase : DrawingArea
+    {
+        private const int SwitchPanelWidth = 1280;
+        private const int SwitchPanelHeight = 720;
+        private const int TargetFps = 60;
+        private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
+        private const float VolumeDelta = 0.05f;
+
+        public ManualResetEvent WaitEvent { get; set; }
+        public NpadManager NpadManager { get; }
+        public TouchScreenManager TouchScreenManager { get; }
+        public Switch Device { get; private set; }
+        public IRenderer Renderer { get; private set; }
+
+        public bool ScreenshotRequested { get; set; }
+        protected int WindowWidth { get; private set; }
+        protected int WindowHeight { get; private set; }
+
+        public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
+
+        private bool _isActive;
+        private bool _isStopped;
+
+        private bool _toggleFullscreen;
+        private bool _toggleDockedMode;
+
+        private readonly long _ticksPerFrame;
+
+        private long _ticks = 0;
+        private float _newVolume;
+
+        private readonly Stopwatch _chrono;
+
+        private KeyboardHotkeyState _prevHotkeyState;
+
+        private readonly ManualResetEvent _exitEvent;
+        private readonly ManualResetEvent _gpuDoneEvent;
+
+        private readonly CancellationTokenSource _gpuCancellationTokenSource;
+
+        // Hide Cursor
+        const int CursorHideIdleTime = 5; // seconds
+        private static readonly Cursor _invisibleCursor = new(Display.Default, CursorType.BlankCursor);
+        private long _lastCursorMoveTime;
+        private HideCursorMode _hideCursorMode;
+        private readonly InputManager _inputManager;
+        private readonly IKeyboard _keyboardInterface;
+        private readonly GraphicsDebugLevel _glLogLevel;
+        private string _gpuBackendName;
+        private string _gpuDriverName;
+        private bool _isMouseInClient;
+
+        public RendererWidgetBase(InputManager inputManager, GraphicsDebugLevel glLogLevel)
+        {
+            var mouseDriver = new GTK3MouseDriver(this);
+
+            _inputManager = inputManager;
+            _inputManager.SetMouseDriver(mouseDriver);
+            NpadManager = _inputManager.CreateNpadManager();
+            TouchScreenManager = _inputManager.CreateTouchScreenManager();
+            _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
+
+            WaitEvent = new ManualResetEvent(false);
+
+            _glLogLevel = glLogLevel;
+
+            Destroyed += Renderer_Destroyed;
+
+            _chrono = new Stopwatch();
+
+            _ticksPerFrame = Stopwatch.Frequency / TargetFps;
+
+            AddEvents((int)(EventMask.ButtonPressMask
+                          | EventMask.ButtonReleaseMask
+                          | EventMask.PointerMotionMask
+                          | EventMask.ScrollMask
+                          | EventMask.EnterNotifyMask
+                          | EventMask.LeaveNotifyMask
+                          | EventMask.KeyPressMask
+                          | EventMask.KeyReleaseMask));
+
+            _exitEvent = new ManualResetEvent(false);
+            _gpuDoneEvent = new ManualResetEvent(false);
+
+            _gpuCancellationTokenSource = new CancellationTokenSource();
+
+            _hideCursorMode = ConfigurationState.Instance.HideCursor;
+            _lastCursorMoveTime = Stopwatch.GetTimestamp();
+
+            ConfigurationState.Instance.HideCursor.Event += HideCursorStateChanged;
+            ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAnriAliasing;
+            ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
+            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
+        }
+
+        private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
+        {
+            Renderer.Window.SetScalingFilter((ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
+            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
+        }
+
+        private void UpdateScalingFilter(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.ScalingFilter> e)
+        {
+            Renderer.Window.SetScalingFilter((ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
+            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
+        }
+
+        public abstract void InitializeRenderer();
+
+        public abstract void SwapBuffers();
+
+        protected abstract string GetGpuBackendName();
+
+        private string GetGpuDriverName()
+        {
+            return Renderer.GetHardwareInfo().GpuDriver;
+        }
+
+        private void HideCursorStateChanged(object sender, ReactiveEventArgs<HideCursorMode> state)
+        {
+            Application.Invoke(delegate
+            {
+                _hideCursorMode = state.NewValue;
+
+                switch (_hideCursorMode)
+                {
+                    case HideCursorMode.Never:
+                        Window.Cursor = null;
+                        break;
+                    case HideCursorMode.OnIdle:
+                        _lastCursorMoveTime = Stopwatch.GetTimestamp();
+                        break;
+                    case HideCursorMode.Always:
+                        Window.Cursor = _invisibleCursor;
+                        break;
+                    default:
+                        throw new ArgumentOutOfRangeException(nameof(state));
+                }
+            });
+        }
+
+        private void Renderer_Destroyed(object sender, EventArgs e)
+        {
+            ConfigurationState.Instance.HideCursor.Event -= HideCursorStateChanged;
+            ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAnriAliasing;
+            ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter;
+            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
+
+            NpadManager.Dispose();
+            Dispose();
+        }
+
+        private void UpdateAnriAliasing(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.AntiAliasing> e)
+        {
+            Renderer?.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue);
+        }
+
+        protected override bool OnMotionNotifyEvent(EventMotion evnt)
+        {
+            if (_hideCursorMode == HideCursorMode.OnIdle)
+            {
+                _lastCursorMoveTime = Stopwatch.GetTimestamp();
+            }
+
+            if (ConfigurationState.Instance.Hid.EnableMouse)
+            {
+                Window.Cursor = _invisibleCursor;
+            }
+
+            _isMouseInClient = true;
+
+            return false;
+        }
+
+        protected override bool OnEnterNotifyEvent(EventCrossing evnt)
+        {
+            Window.Cursor = ConfigurationState.Instance.Hid.EnableMouse ? _invisibleCursor : null;
+
+            _isMouseInClient = true;
+
+            return base.OnEnterNotifyEvent(evnt);
+        }
+
+        protected override bool OnLeaveNotifyEvent(EventCrossing evnt)
+        {
+            Window.Cursor = null;
+
+            _isMouseInClient = false;
+
+            return base.OnLeaveNotifyEvent(evnt);
+        }
+
+        protected override void OnGetPreferredHeight(out int minimumHeight, out int naturalHeight)
+        {
+            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
+
+            // If the monitor is at least 1080p, use the Switch panel size as minimal size.
+            if (monitor.Geometry.Height >= 1080)
+            {
+                minimumHeight = SwitchPanelHeight;
+            }
+            // Otherwise, we default minimal size to 480p 16:9.
+            else
+            {
+                minimumHeight = 480;
+            }
+
+            naturalHeight = minimumHeight;
+        }
+
+        protected override void OnGetPreferredWidth(out int minimumWidth, out int naturalWidth)
+        {
+            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
+
+            // If the monitor is at least 1080p, use the Switch panel size as minimal size.
+            if (monitor.Geometry.Height >= 1080)
+            {
+                minimumWidth = SwitchPanelWidth;
+            }
+            // Otherwise, we default minimal size to 480p 16:9.
+            else
+            {
+                minimumWidth = 854;
+            }
+
+            naturalWidth = minimumWidth;
+        }
+
+        protected override bool OnConfigureEvent(EventConfigure evnt)
+        {
+            bool result = base.OnConfigureEvent(evnt);
+
+            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
+
+            WindowWidth = evnt.Width * monitor.ScaleFactor;
+            WindowHeight = evnt.Height * monitor.ScaleFactor;
+
+            Renderer?.Window?.SetSize(WindowWidth, WindowHeight);
+
+            return result;
+        }
+
+        private void HandleScreenState(KeyboardStateSnapshot keyboard)
+        {
+            bool toggleFullscreen = keyboard.IsPressed(Key.F11)
+                                || ((keyboard.IsPressed(Key.AltLeft)
+                                || keyboard.IsPressed(Key.AltRight))
+                                && keyboard.IsPressed(Key.Enter))
+                                || keyboard.IsPressed(Key.Escape);
+
+            bool fullScreenToggled = ParentWindow.State.HasFlag(WindowState.Fullscreen);
+
+            if (toggleFullscreen != _toggleFullscreen)
+            {
+                if (toggleFullscreen)
+                {
+                    if (fullScreenToggled)
+                    {
+                        ParentWindow.Unfullscreen();
+                        (Toplevel as MainWindow)?.ToggleExtraWidgets(true);
+                    }
+                    else
+                    {
+                        if (keyboard.IsPressed(Key.Escape))
+                        {
+                            if (!ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
+                            {
+                                Exit();
+                            }
+                        }
+                        else
+                        {
+                            ParentWindow.Fullscreen();
+                            (Toplevel as MainWindow)?.ToggleExtraWidgets(false);
+                        }
+                    }
+                }
+            }
+
+            _toggleFullscreen = toggleFullscreen;
+
+            bool toggleDockedMode = keyboard.IsPressed(Key.F9);
+
+            if (toggleDockedMode != _toggleDockedMode)
+            {
+                if (toggleDockedMode)
+                {
+                    ConfigurationState.Instance.System.EnableDockedMode.Value =
+                        !ConfigurationState.Instance.System.EnableDockedMode.Value;
+                }
+            }
+
+            _toggleDockedMode = toggleDockedMode;
+
+            if (_isMouseInClient)
+            {
+                if (ConfigurationState.Instance.Hid.EnableMouse.Value)
+                {
+                    Window.Cursor = _invisibleCursor;
+                }
+                else
+                {
+                    switch (_hideCursorMode)
+                    {
+                        case HideCursorMode.OnIdle:
+                            long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
+                            Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
+                            break;
+                        case HideCursorMode.Always:
+                            Window.Cursor = _invisibleCursor;
+                            break;
+                        case HideCursorMode.Never:
+                            Window.Cursor = null;
+                            break;
+                    }
+                }
+            }
+        }
+
+        public void Initialize(Switch device)
+        {
+            Device = device;
+
+            IRenderer renderer = Device.Gpu.Renderer;
+
+            if (renderer is ThreadedRenderer tr)
+            {
+                renderer = tr.BaseRenderer;
+            }
+
+            Renderer = renderer;
+            Renderer?.Window?.SetSize(WindowWidth, WindowHeight);
+
+            if (Renderer != null)
+            {
+                Renderer.ScreenCaptured += Renderer_ScreenCaptured;
+            }
+
+            NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
+            TouchScreenManager.Initialize(device);
+        }
+
+        private unsafe void Renderer_ScreenCaptured(object sender, ScreenCaptureImageInfo e)
+        {
+            if (e.Data.Length > 0 && e.Height > 0 && e.Width > 0)
+            {
+                Task.Run(() =>
+                {
+                    lock (this)
+                    {
+                        var currentTime = DateTime.Now;
+                        string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
+                        string directory = AppDataManager.Mode switch
+                        {
+                            AppDataManager.LaunchMode.Portable or AppDataManager.LaunchMode.Custom => System.IO.Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
+                            _ => System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx"),
+                        };
+
+                        string path = System.IO.Path.Combine(directory, filename);
+
+                        try
+                        {
+                            Directory.CreateDirectory(directory);
+                        }
+                        catch (Exception ex)
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"Failed to create directory at path {directory}. Error : {ex.GetType().Name}", "Screenshot");
+
+                            return;
+                        }
+
+                        Image image = e.IsBgra ? Image.LoadPixelData<Bgra32>(e.Data, e.Width, e.Height)
+                                               : Image.LoadPixelData<Rgba32>(e.Data, e.Width, e.Height);
+
+                        if (e.FlipX)
+                        {
+                            image.Mutate(x => x.Flip(FlipMode.Horizontal));
+                        }
+
+                        if (e.FlipY)
+                        {
+                            image.Mutate(x => x.Flip(FlipMode.Vertical));
+                        }
+
+                        image.SaveAsPng(path, new PngEncoder()
+                        {
+                            ColorType = PngColorType.Rgb,
+                        });
+
+                        image.Dispose();
+
+                        Logger.Notice.Print(LogClass.Application, $"Screenshot saved to {path}", "Screenshot");
+                    }
+                });
+            }
+            else
+            {
+                Logger.Error?.Print(LogClass.Application, $"Screenshot is empty. Size : {e.Data.Length} bytes. Resolution : {e.Width}x{e.Height}", "Screenshot");
+            }
+        }
+
+        public void Render()
+        {
+            Gtk.Window parent = Toplevel as Gtk.Window;
+            parent.Present();
+
+            InitializeRenderer();
+
+            Device.Gpu.Renderer.Initialize(_glLogLevel);
+
+            Renderer.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value);
+            Renderer.Window.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
+            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
+
+            _gpuBackendName = GetGpuBackendName();
+            _gpuDriverName = GetGpuDriverName();
+
+            Device.Gpu.Renderer.RunLoop(() =>
+            {
+                Device.Gpu.SetGpuThread();
+                Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
+
+                Renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
+
+                (Toplevel as MainWindow)?.ActivatePauseMenu();
+
+                while (_isActive)
+                {
+                    if (_isStopped)
+                    {
+                        return;
+                    }
+
+                    _ticks += _chrono.ElapsedTicks;
+
+                    _chrono.Restart();
+
+                    if (Device.WaitFifo())
+                    {
+                        Device.Statistics.RecordFifoStart();
+                        Device.ProcessFrame();
+                        Device.Statistics.RecordFifoEnd();
+                    }
+
+                    while (Device.ConsumeFrameAvailable())
+                    {
+                        Device.PresentFrame(SwapBuffers);
+                    }
+
+                    if (_ticks >= _ticksPerFrame)
+                    {
+                        string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? "Docked" : "Handheld";
+                        float scale = GraphicsConfig.ResScale;
+                        if (scale != 1)
+                        {
+                            dockedMode += $" ({scale}x)";
+                        }
+
+                        StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
+                            Device.EnableDeviceVsync,
+                            Device.GetVolume(),
+                            _gpuBackendName,
+                            dockedMode,
+                            ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
+                            $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
+                            $"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
+                            $"GPU: {_gpuDriverName}"));
+
+                        _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
+                    }
+                }
+
+                // Make sure all commands in the run loop are fully executed before leaving the loop.
+                if (Device.Gpu.Renderer is ThreadedRenderer threaded)
+                {
+                    threaded.FlushThreadedCommands();
+                }
+
+                _gpuDoneEvent.Set();
+            });
+        }
+
+        public void Start()
+        {
+            _chrono.Restart();
+
+            _isActive = true;
+
+            Gtk.Window parent = Toplevel as Gtk.Window;
+
+            Application.Invoke(delegate
+            {
+                parent.Present();
+
+                var activeProcess = Device.Processes.ActiveApplication;
+
+                parent.Title = TitleHelper.ActiveApplicationTitle(activeProcess, Program.Version);
+            });
+
+            Thread renderLoopThread = new(Render)
+            {
+                Name = "GUI.RenderLoop",
+            };
+            renderLoopThread.Start();
+
+            Thread nvidiaStutterWorkaround = null;
+            if (Renderer is Graphics.OpenGL.OpenGLRenderer)
+            {
+                nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround)
+                {
+                    Name = "GUI.NvidiaStutterWorkaround",
+                };
+                nvidiaStutterWorkaround.Start();
+            }
+
+            MainLoop();
+
+            // NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
+            // We only need to wait for all commands submitted during the main gpu loop to be processed.
+            _gpuDoneEvent.WaitOne();
+            _gpuDoneEvent.Dispose();
+            nvidiaStutterWorkaround?.Join();
+
+            Exit();
+        }
+
+        public void Exit()
+        {
+            TouchScreenManager?.Dispose();
+            NpadManager?.Dispose();
+
+            if (_isStopped)
+            {
+                return;
+            }
+
+            _gpuCancellationTokenSource.Cancel();
+
+            _isStopped = true;
+
+            if (_isActive)
+            {
+                _isActive = false;
+
+                _exitEvent.WaitOne();
+                _exitEvent.Dispose();
+            }
+        }
+
+        private void NvidiaStutterWorkaround()
+        {
+            while (_isActive)
+            {
+                // When NVIDIA Threaded Optimization is on, the driver will snapshot all threads in the system whenever the application creates any new ones.
+                // The ThreadPool has something called a "GateThread" which terminates itself after some inactivity.
+                // However, it immediately starts up again, since the rules regarding when to terminate and when to start differ.
+                // This creates a new thread every second or so.
+                // The main problem with this is that the thread snapshot can take 70ms, is on the OpenGL thread and will delay rendering any graphics.
+                // This is a little over budget on a frame time of 16ms, so creates a large stutter.
+                // The solution is to keep the ThreadPool active so that it never has a reason to terminate the GateThread.
+
+                // TODO: This should be removed when the issue with the GateThread is resolved.
+
+                ThreadPool.QueueUserWorkItem((state) => { });
+                Thread.Sleep(300);
+            }
+        }
+
+        public void MainLoop()
+        {
+            while (_isActive)
+            {
+                UpdateFrame();
+
+                // Polling becomes expensive if it's not slept
+                Thread.Sleep(1);
+            }
+
+            _exitEvent.Set();
+        }
+
+        private bool UpdateFrame()
+        {
+            if (!_isActive)
+            {
+                return true;
+            }
+
+            if (_isStopped)
+            {
+                return false;
+            }
+
+            if ((Toplevel as MainWindow).IsFocused)
+            {
+                Application.Invoke(delegate
+                {
+                    KeyboardStateSnapshot keyboard = _keyboardInterface.GetKeyboardStateSnapshot();
+
+                    HandleScreenState(keyboard);
+
+                    if (keyboard.IsPressed(Key.Delete))
+                    {
+                        if (!ParentWindow.State.HasFlag(WindowState.Fullscreen))
+                        {
+                            Device.Processes.ActiveApplication.DiskCacheLoadState?.Cancel();
+                        }
+                    }
+                });
+            }
+
+            NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
+
+            if ((Toplevel as MainWindow).IsFocused)
+            {
+                KeyboardHotkeyState currentHotkeyState = GetHotkeyState();
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync))
+                {
+                    Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
+                }
+
+                if ((currentHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot)) || ScreenshotRequested)
+                {
+                    ScreenshotRequested = false;
+
+                    Renderer.Screenshot();
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ShowUI) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ShowUI))
+                {
+                    (Toplevel as MainWindow).ToggleExtraWidgets(true);
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.Pause) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.Pause))
+                {
+                    (Toplevel as MainWindow)?.TogglePause();
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleMute) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleMute))
+                {
+                    if (Device.IsAudioMuted())
+                    {
+                        Device.SetVolume(ConfigurationState.Instance.System.AudioVolume);
+                    }
+                    else
+                    {
+                        Device.SetVolume(0);
+                    }
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleUp) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleUp))
+                {
+                    GraphicsConfig.ResScale = GraphicsConfig.ResScale % MaxResolutionScale + 1;
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleDown) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleDown))
+                {
+                    GraphicsConfig.ResScale =
+                    (MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.VolumeUp) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.VolumeUp))
+                {
+                    _newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
+                    Device.SetVolume(_newVolume);
+                }
+
+                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.VolumeDown) &&
+                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.VolumeDown))
+                {
+                    _newVolume = MathF.Round((Device.GetVolume() - VolumeDelta), 2);
+                    Device.SetVolume(_newVolume);
+                }
+
+                _prevHotkeyState = currentHotkeyState;
+            }
+
+            // Touchscreen
+            bool hasTouch = false;
+
+            // Get screen touch position
+            if ((Toplevel as MainWindow).IsFocused && !ConfigurationState.Instance.Hid.EnableMouse)
+            {
+                hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as GTK3MouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
+            }
+
+            if (!hasTouch)
+            {
+                TouchScreenManager.Update(false);
+            }
+
+            Device.Hid.DebugPad.Update();
+
+            return true;
+        }
+
+        [Flags]
+        private enum KeyboardHotkeyState
+        {
+            None = 0,
+            ToggleVSync = 1 << 0,
+            Screenshot = 1 << 1,
+            ShowUI = 1 << 2,
+            Pause = 1 << 3,
+            ToggleMute = 1 << 4,
+            ResScaleUp = 1 << 5,
+            ResScaleDown = 1 << 6,
+            VolumeUp = 1 << 7,
+            VolumeDown = 1 << 8,
+        }
+
+        private KeyboardHotkeyState GetHotkeyState()
+        {
+            KeyboardHotkeyState state = KeyboardHotkeyState.None;
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
+            {
+                state |= KeyboardHotkeyState.ToggleVSync;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
+            {
+                state |= KeyboardHotkeyState.Screenshot;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI))
+            {
+                state |= KeyboardHotkeyState.ShowUI;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
+            {
+                state |= KeyboardHotkeyState.Pause;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute))
+            {
+                state |= KeyboardHotkeyState.ToggleMute;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp))
+            {
+                state |= KeyboardHotkeyState.ResScaleUp;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown))
+            {
+                state |= KeyboardHotkeyState.ResScaleDown;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
+            {
+                state |= KeyboardHotkeyState.VolumeUp;
+            }
+
+            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
+            {
+                state |= KeyboardHotkeyState.VolumeDown;
+            }
+
+            return state;
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/SPBOpenGLContext.cs b/src/Ryujinx/UI/SPBOpenGLContext.cs
new file mode 100644
index 00000000..97feb434
--- /dev/null
+++ b/src/Ryujinx/UI/SPBOpenGLContext.cs
@@ -0,0 +1,49 @@
+using OpenTK.Graphics.OpenGL;
+using Ryujinx.Graphics.OpenGL;
+using SPB.Graphics;
+using SPB.Graphics.OpenGL;
+using SPB.Platform;
+using SPB.Windowing;
+
+namespace Ryujinx.UI
+{
+    class SPBOpenGLContext : IOpenGLContext
+    {
+        private readonly OpenGLContextBase _context;
+        private readonly NativeWindowBase _window;
+
+        private SPBOpenGLContext(OpenGLContextBase context, NativeWindowBase window)
+        {
+            _context = context;
+            _window = window;
+        }
+
+        public void Dispose()
+        {
+            _context.Dispose();
+            _window.Dispose();
+        }
+
+        public void MakeCurrent()
+        {
+            _context.MakeCurrent(_window);
+        }
+
+        public bool HasContext() => _context.IsCurrent;
+
+        public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
+        {
+            OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);
+            NativeWindowBase window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100);
+
+            context.Initialize(window);
+            context.MakeCurrent(window);
+
+            GL.LoadBindings(new OpenToolkitBindingsContext(context));
+
+            context.MakeCurrent(null);
+
+            return new SPBOpenGLContext(context, window);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/StatusUpdatedEventArgs.cs b/src/Ryujinx/UI/StatusUpdatedEventArgs.cs
new file mode 100644
index 00000000..db467ebf
--- /dev/null
+++ b/src/Ryujinx/UI/StatusUpdatedEventArgs.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Ryujinx.UI
+{
+    public class StatusUpdatedEventArgs : EventArgs
+    {
+        public bool VSyncEnabled;
+        public float Volume;
+        public string DockedMode;
+        public string AspectRatio;
+        public string GameStatus;
+        public string FifoStatus;
+        public string GpuName;
+        public string GpuBackend;
+
+        public StatusUpdatedEventArgs(bool vSyncEnabled, float volume, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName)
+        {
+            VSyncEnabled = vSyncEnabled;
+            Volume = volume;
+            GpuBackend = gpuBackend;
+            DockedMode = dockedMode;
+            AspectRatio = aspectRatio;
+            GameStatus = gameStatus;
+            FifoStatus = fifoStatus;
+            GpuName = gpuName;
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/VulkanRenderer.cs b/src/Ryujinx/UI/VulkanRenderer.cs
new file mode 100644
index 00000000..eefc5699
--- /dev/null
+++ b/src/Ryujinx/UI/VulkanRenderer.cs
@@ -0,0 +1,93 @@
+using Gdk;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Input.HLE;
+using Ryujinx.UI.Helper;
+using SPB.Graphics.Vulkan;
+using SPB.Platform.Metal;
+using SPB.Platform.Win32;
+using SPB.Platform.X11;
+using SPB.Windowing;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.UI
+{
+    public partial class VulkanRenderer : RendererWidgetBase
+    {
+        public NativeWindowBase NativeWindow { get; private set; }
+        private UpdateBoundsCallbackDelegate _updateBoundsCallback;
+
+        public VulkanRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel) { }
+
+        private NativeWindowBase RetrieveNativeWindow()
+        {
+            if (OperatingSystem.IsWindows())
+            {
+                IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);
+
+                return new SimpleWin32Window(new NativeHandle(windowHandle));
+            }
+            else if (OperatingSystem.IsLinux())
+            {
+                IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
+                IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
+
+                return new SimpleX11Window(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
+            }
+            else if (OperatingSystem.IsMacOS())
+            {
+                IntPtr metalLayer = MetalHelper.GetMetalLayer(Display, Window, out IntPtr nsView, out _updateBoundsCallback);
+
+                return new SimpleMetalWindow(new NativeHandle(nsView), new NativeHandle(metalLayer));
+            }
+
+            throw new NotImplementedException();
+        }
+
+        [LibraryImport("libgdk-3-0.dll")]
+        private static partial IntPtr gdk_win32_window_get_handle(IntPtr d);
+
+        [LibraryImport("libgdk-3.so.0")]
+        private static partial IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
+
+        [LibraryImport("libgdk-3.so.0")]
+        private static partial IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);
+
+        protected override bool OnConfigureEvent(EventConfigure evnt)
+        {
+            if (NativeWindow == null)
+            {
+                NativeWindow = RetrieveNativeWindow();
+
+                WaitEvent.Set();
+            }
+
+            bool result = base.OnConfigureEvent(evnt);
+
+            _updateBoundsCallback?.Invoke(Window);
+
+            return result;
+        }
+
+        public unsafe IntPtr CreateWindowSurface(IntPtr instance)
+        {
+            return VulkanHelper.CreateWindowSurface(instance, NativeWindow);
+        }
+
+        public override void InitializeRenderer() { }
+
+        public override void SwapBuffers() { }
+
+        protected override string GetGpuBackendName()
+        {
+            return "Vulkan";
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            Device?.DisposeGpu();
+
+            NpadManager.Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/GameTableContextMenu.Designer.cs b/src/Ryujinx/UI/Widgets/GameTableContextMenu.Designer.cs
new file mode 100644
index 00000000..8ee1cd2f
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/GameTableContextMenu.Designer.cs
@@ -0,0 +1,233 @@
+using Gtk;
+using System;
+
+namespace Ryujinx.UI.Widgets
+{
+    public partial class GameTableContextMenu : Menu
+    {
+        private MenuItem _openSaveUserDirMenuItem;
+        private MenuItem _openSaveDeviceDirMenuItem;
+        private MenuItem _openSaveBcatDirMenuItem;
+        private MenuItem _manageTitleUpdatesMenuItem;
+        private MenuItem _manageDlcMenuItem;
+        private MenuItem _manageCheatMenuItem;
+        private MenuItem _openTitleModDirMenuItem;
+        private MenuItem _openTitleSdModDirMenuItem;
+        private Menu _extractSubMenu;
+        private MenuItem _extractMenuItem;
+        private MenuItem _extractRomFsMenuItem;
+        private MenuItem _extractExeFsMenuItem;
+        private MenuItem _extractLogoMenuItem;
+        private Menu _manageSubMenu;
+        private MenuItem _manageCacheMenuItem;
+        private MenuItem _purgePtcCacheMenuItem;
+        private MenuItem _purgeShaderCacheMenuItem;
+        private MenuItem _openPtcDirMenuItem;
+        private MenuItem _openShaderCacheDirMenuItem;
+        private MenuItem _createShortcutMenuItem;
+
+        private void InitializeComponent()
+        {
+            //
+            // _openSaveUserDirMenuItem
+            //
+            _openSaveUserDirMenuItem = new MenuItem("Open User Save Directory")
+            {
+                TooltipText = "Open the directory which contains Application's User Saves.",
+            };
+            _openSaveUserDirMenuItem.Activated += OpenSaveUserDir_Clicked;
+
+            //
+            // _openSaveDeviceDirMenuItem
+            //
+            _openSaveDeviceDirMenuItem = new MenuItem("Open Device Save Directory")
+            {
+                TooltipText = "Open the directory which contains Application's Device Saves.",
+            };
+            _openSaveDeviceDirMenuItem.Activated += OpenSaveDeviceDir_Clicked;
+
+            //
+            // _openSaveBcatDirMenuItem
+            //
+            _openSaveBcatDirMenuItem = new MenuItem("Open BCAT Save Directory")
+            {
+                TooltipText = "Open the directory which contains Application's BCAT Saves.",
+            };
+            _openSaveBcatDirMenuItem.Activated += OpenSaveBcatDir_Clicked;
+
+            //
+            // _manageTitleUpdatesMenuItem
+            //
+            _manageTitleUpdatesMenuItem = new MenuItem("Manage Title Updates")
+            {
+                TooltipText = "Open the Title Update management window",
+            };
+            _manageTitleUpdatesMenuItem.Activated += ManageTitleUpdates_Clicked;
+
+            //
+            // _manageDlcMenuItem
+            //
+            _manageDlcMenuItem = new MenuItem("Manage DLC")
+            {
+                TooltipText = "Open the DLC management window",
+            };
+            _manageDlcMenuItem.Activated += ManageDlc_Clicked;
+
+            //
+            // _manageCheatMenuItem
+            //
+            _manageCheatMenuItem = new MenuItem("Manage Cheats")
+            {
+                TooltipText = "Open the Cheat management window",
+            };
+            _manageCheatMenuItem.Activated += ManageCheats_Clicked;
+
+            //
+            // _openTitleModDirMenuItem
+            //
+            _openTitleModDirMenuItem = new MenuItem("Open Mods Directory")
+            {
+                TooltipText = "Open the directory which contains Application's Mods.",
+            };
+            _openTitleModDirMenuItem.Activated += OpenTitleModDir_Clicked;
+
+            //
+            // _openTitleSdModDirMenuItem
+            //
+            _openTitleSdModDirMenuItem = new MenuItem("Open Atmosphere Mods Directory")
+            {
+                TooltipText = "Open the alternative SD card atmosphere directory which contains the Application's Mods.",
+            };
+            _openTitleSdModDirMenuItem.Activated += OpenTitleSdModDir_Clicked;
+
+            //
+            // _extractSubMenu
+            //
+            _extractSubMenu = new Menu();
+
+            //
+            // _extractMenuItem
+            //
+            _extractMenuItem = new MenuItem("Extract Data")
+            {
+                Submenu = _extractSubMenu
+            };
+
+            //
+            // _extractRomFsMenuItem
+            //
+            _extractRomFsMenuItem = new MenuItem("RomFS")
+            {
+                TooltipText = "Extract the RomFS section from Application's current config (including updates).",
+            };
+            _extractRomFsMenuItem.Activated += ExtractRomFs_Clicked;
+
+            //
+            // _extractExeFsMenuItem
+            //
+            _extractExeFsMenuItem = new MenuItem("ExeFS")
+            {
+                TooltipText = "Extract the ExeFS section from Application's current config (including updates).",
+            };
+            _extractExeFsMenuItem.Activated += ExtractExeFs_Clicked;
+
+            //
+            // _extractLogoMenuItem
+            //
+            _extractLogoMenuItem = new MenuItem("Logo")
+            {
+                TooltipText = "Extract the Logo section from Application's current config (including updates).",
+            };
+            _extractLogoMenuItem.Activated += ExtractLogo_Clicked;
+
+            //
+            // _manageSubMenu
+            //
+            _manageSubMenu = new Menu();
+
+            //
+            // _manageCacheMenuItem
+            //
+            _manageCacheMenuItem = new MenuItem("Cache Management")
+            {
+                Submenu = _manageSubMenu,
+            };
+
+            //
+            // _purgePtcCacheMenuItem
+            //
+            _purgePtcCacheMenuItem = new MenuItem("Queue PPTC Rebuild")
+            {
+                TooltipText = "Trigger PPTC to rebuild at boot time on the next game launch.",
+            };
+            _purgePtcCacheMenuItem.Activated += PurgePtcCache_Clicked;
+
+            //
+            // _purgeShaderCacheMenuItem
+            //
+            _purgeShaderCacheMenuItem = new MenuItem("Purge Shader Cache")
+            {
+                TooltipText = "Delete the Application's shader cache.",
+            };
+            _purgeShaderCacheMenuItem.Activated += PurgeShaderCache_Clicked;
+
+            //
+            // _openPtcDirMenuItem
+            //
+            _openPtcDirMenuItem = new MenuItem("Open PPTC Directory")
+            {
+                TooltipText = "Open the directory which contains the Application's PPTC cache.",
+            };
+            _openPtcDirMenuItem.Activated += OpenPtcDir_Clicked;
+
+            //
+            // _openShaderCacheDirMenuItem
+            //
+            _openShaderCacheDirMenuItem = new MenuItem("Open Shader Cache Directory")
+            {
+                TooltipText = "Open the directory which contains the Application's shader cache.",
+            };
+            _openShaderCacheDirMenuItem.Activated += OpenShaderCacheDir_Clicked;
+
+            //
+            // _createShortcutMenuItem
+            //
+            _createShortcutMenuItem = new MenuItem("Create Application Shortcut")
+            {
+                TooltipText = OperatingSystem.IsMacOS() ? "Create a shortcut in macOS's Applications folder that launches the selected Application" : "Create a Desktop Shortcut that launches the selected Application."
+            };
+            _createShortcutMenuItem.Activated += CreateShortcut_Clicked;
+
+            ShowComponent();
+        }
+
+        private void ShowComponent()
+        {
+            _extractSubMenu.Append(_extractExeFsMenuItem);
+            _extractSubMenu.Append(_extractRomFsMenuItem);
+            _extractSubMenu.Append(_extractLogoMenuItem);
+
+            _manageSubMenu.Append(_purgePtcCacheMenuItem);
+            _manageSubMenu.Append(_purgeShaderCacheMenuItem);
+            _manageSubMenu.Append(_openPtcDirMenuItem);
+            _manageSubMenu.Append(_openShaderCacheDirMenuItem);
+
+            Add(_createShortcutMenuItem);
+            Add(new SeparatorMenuItem());
+            Add(_openSaveUserDirMenuItem);
+            Add(_openSaveDeviceDirMenuItem);
+            Add(_openSaveBcatDirMenuItem);
+            Add(new SeparatorMenuItem());
+            Add(_manageTitleUpdatesMenuItem);
+            Add(_manageDlcMenuItem);
+            Add(_manageCheatMenuItem);
+            Add(_openTitleModDirMenuItem);
+            Add(_openTitleSdModDirMenuItem);
+            Add(new SeparatorMenuItem());
+            Add(_manageCacheMenuItem);
+            Add(_extractMenuItem);
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/GameTableContextMenu.cs b/src/Ryujinx/UI/Widgets/GameTableContextMenu.cs
new file mode 100644
index 00000000..dc0dd4c5
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/GameTableContextMenu.cs
@@ -0,0 +1,644 @@
+using Gtk;
+using LibHac;
+using LibHac.Account;
+using LibHac.Common;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.Fs.Shim;
+using LibHac.FsSystem;
+using LibHac.Ns;
+using LibHac.Tools.Fs;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS;
+using Ryujinx.HLE.HOS.Services.Account.Acc;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Helper;
+using Ryujinx.UI.Windows;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+
+namespace Ryujinx.UI.Widgets
+{
+    public partial class GameTableContextMenu : Menu
+    {
+        private readonly MainWindow _parent;
+        private readonly VirtualFileSystem _virtualFileSystem;
+        private readonly AccountManager _accountManager;
+        private readonly HorizonClient _horizonClient;
+        private readonly BlitStruct<ApplicationControlProperty> _controlData;
+
+        private readonly string _titleFilePath;
+        private readonly string _titleName;
+        private readonly string _titleIdText;
+        private readonly ulong _titleId;
+
+        private MessageDialog _dialog;
+        private bool _cancel;
+
+        public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, AccountManager accountManager, HorizonClient horizonClient, string titleFilePath, string titleName, string titleId, BlitStruct<ApplicationControlProperty> controlData)
+        {
+            _parent = parent;
+
+            InitializeComponent();
+
+            _virtualFileSystem = virtualFileSystem;
+            _accountManager = accountManager;
+            _horizonClient = horizonClient;
+            _titleFilePath = titleFilePath;
+            _titleName = titleName;
+            _titleIdText = titleId;
+            _controlData = controlData;
+
+            if (!ulong.TryParse(_titleIdText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _titleId))
+            {
+                GtkDialog.CreateErrorDialog("The selected game did not have a valid Title Id");
+
+                return;
+            }
+
+            _openSaveUserDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.UserAccountSaveDataSize > 0;
+            _openSaveDeviceDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.DeviceSaveDataSize > 0;
+            _openSaveBcatDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.BcatDeliveryCacheStorageSize > 0;
+
+            string fileExt = System.IO.Path.GetExtension(_titleFilePath).ToLower();
+            bool hasNca = fileExt == ".nca" || fileExt == ".nsp" || fileExt == ".pfs0" || fileExt == ".xci";
+
+            _extractRomFsMenuItem.Sensitive = hasNca;
+            _extractExeFsMenuItem.Sensitive = hasNca;
+            _extractLogoMenuItem.Sensitive = hasNca;
+
+            _createShortcutMenuItem.Sensitive = !ReleaseInformation.IsFlatHubBuild;
+
+            PopupAtPointer(null);
+        }
+
+        private bool TryFindSaveData(string titleName, ulong titleId, BlitStruct<ApplicationControlProperty> controlHolder, in SaveDataFilter filter, out ulong saveDataId)
+        {
+            saveDataId = default;
+
+            Result result = _horizonClient.Fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, in filter);
+
+            if (ResultFs.TargetNotFound.Includes(result))
+            {
+                ref ApplicationControlProperty control = ref controlHolder.Value;
+
+                Logger.Info?.Print(LogClass.Application, $"Creating save directory for Title: {titleName} [{titleId:x16}]");
+
+                if (Utilities.IsZeros(controlHolder.ByteSpan))
+                {
+                    // If the current application doesn't have a loaded control property, create a dummy one
+                    // and set the savedata sizes so a user savedata will be created.
+                    control = ref new BlitStruct<ApplicationControlProperty>(1).Value;
+
+                    // The set sizes don't actually matter as long as they're non-zero because we use directory savedata.
+                    control.UserAccountSaveDataSize = 0x4000;
+                    control.UserAccountSaveDataJournalSize = 0x4000;
+
+                    Logger.Warning?.Print(LogClass.Application, "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
+                }
+
+                Uid user = new((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
+
+                result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user);
+
+                if (result.IsFailure())
+                {
+                    GtkDialog.CreateErrorDialog($"There was an error creating the specified savedata: {result.ToStringWithName()}");
+
+                    return false;
+                }
+
+                // Try to find the savedata again after creating it
+                result = _horizonClient.Fs.FindSaveDataWithFilter(out saveDataInfo, SaveDataSpaceId.User, in filter);
+            }
+
+            if (result.IsSuccess())
+            {
+                saveDataId = saveDataInfo.SaveDataId;
+
+                return true;
+            }
+
+            GtkDialog.CreateErrorDialog($"There was an error finding the specified savedata: {result.ToStringWithName()}");
+
+            return false;
+        }
+
+        private void OpenSaveDir(in SaveDataFilter saveDataFilter)
+        {
+            if (!TryFindSaveData(_titleName, _titleId, _controlData, in saveDataFilter, out ulong saveDataId))
+            {
+                return;
+            }
+
+            string saveRootPath = System.IO.Path.Combine(VirtualFileSystem.GetNandPath(), $"user/save/{saveDataId:x16}");
+
+            if (!Directory.Exists(saveRootPath))
+            {
+                // Inconsistent state. Create the directory
+                Directory.CreateDirectory(saveRootPath);
+            }
+
+            string committedPath = System.IO.Path.Combine(saveRootPath, "0");
+            string workingPath = System.IO.Path.Combine(saveRootPath, "1");
+
+            // If the committed directory exists, that path will be loaded the next time the savedata is mounted
+            if (Directory.Exists(committedPath))
+            {
+                OpenHelper.OpenFolder(committedPath);
+            }
+            else
+            {
+                // If the working directory exists and the committed directory doesn't,
+                // the working directory will be loaded the next time the savedata is mounted
+                if (!Directory.Exists(workingPath))
+                {
+                    Directory.CreateDirectory(workingPath);
+                }
+
+                OpenHelper.OpenFolder(workingPath);
+            }
+        }
+
+        private void ExtractSection(NcaSectionType ncaSectionType, int programIndex = 0)
+        {
+            FileChooserNative fileChooser = new("Choose the folder to extract into", _parent, FileChooserAction.SelectFolder, "Extract", "Cancel");
+
+            ResponseType response = (ResponseType)fileChooser.Run();
+            string destination = fileChooser.Filename;
+
+            fileChooser.Dispose();
+
+            if (response == ResponseType.Accept)
+            {
+                Thread extractorThread = new(() =>
+                {
+                    Gtk.Application.Invoke(delegate
+                    {
+                        _dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Cancel, null)
+                        {
+                            Title = "Ryujinx - NCA Section Extractor",
+                            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png"),
+                            SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_titleFilePath)}...",
+                            WindowPosition = WindowPosition.Center,
+                        };
+
+                        int dialogResponse = _dialog.Run();
+                        if (dialogResponse == (int)ResponseType.Cancel || dialogResponse == (int)ResponseType.DeleteEvent)
+                        {
+                            _cancel = true;
+                            _dialog.Dispose();
+                        }
+                    });
+
+                    using FileStream file = new(_titleFilePath, FileMode.Open, FileAccess.Read);
+
+                    Nca mainNca = null;
+                    Nca patchNca = null;
+
+                    if ((System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nsp") ||
+                        (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".pfs0") ||
+                        (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".xci"))
+                    {
+                        IFileSystem pfs;
+
+                        if (System.IO.Path.GetExtension(_titleFilePath) == ".xci")
+                        {
+                            Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
+
+                            pfs = xci.OpenPartition(XciPartitionType.Secure);
+                        }
+                        else
+                        {
+                            var pfsTemp = new PartitionFileSystem();
+                            pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                            pfs = pfsTemp;
+                        }
+
+                        foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
+                        {
+                            using var ncaFile = new UniqueRef<IFile>();
+
+                            pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                            Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Release().AsStorage());
+
+                            if (nca.Header.ContentType == NcaContentType.Program)
+                            {
+                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
+
+                                if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
+                                {
+                                    patchNca = nca;
+                                }
+                                else
+                                {
+                                    mainNca = nca;
+                                }
+                            }
+                        }
+                    }
+                    else if (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nca")
+                    {
+                        mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
+                    }
+
+                    if (mainNca == null)
+                    {
+                        Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA is not present in the selected file.");
+
+                        Gtk.Application.Invoke(delegate
+                            {
+                                GtkDialog.CreateErrorDialog("Extraction failure. The main NCA is not present in the selected file.");
+                            });
+
+                        return;
+                    }
+
+                    (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _);
+
+                    if (updatePatchNca != null)
+                    {
+                        patchNca = updatePatchNca;
+                    }
+
+                    int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);
+
+                    bool sectionExistsInPatch = false;
+
+                    if (patchNca != null)
+                    {
+                        sectionExistsInPatch = patchNca.CanOpenSection(index);
+                    }
+
+                    IFileSystem ncaFileSystem = sectionExistsInPatch ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)
+                                                                         : mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);
+
+                    FileSystemClient fsClient = _horizonClient.Fs;
+
+                    string source = DateTime.Now.ToFileTime().ToString()[10..];
+                    string output = DateTime.Now.ToFileTime().ToString()[10..];
+
+                    using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem);
+                    using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination));
+
+                    fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref);
+                    fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref);
+
+                    (Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/");
+
+                    if (!canceled)
+                    {
+                        if (resultCode.Value.IsFailure())
+                        {
+                            Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}");
+
+                            Gtk.Application.Invoke(delegate
+                                {
+                                    _dialog?.Dispose();
+
+                                    GtkDialog.CreateErrorDialog("Extraction failed. Read the log file for further information.");
+                                });
+                        }
+                        else if (resultCode.Value.IsSuccess())
+                        {
+                            Gtk.Application.Invoke(delegate
+                                {
+                                    _dialog?.Dispose();
+
+                                    MessageDialog dialog = new(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
+                                    {
+                                        Title = "Ryujinx - NCA Section Extractor",
+                                        Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png"),
+                                        SecondaryText = "Extraction completed successfully.",
+                                        WindowPosition = WindowPosition.Center,
+                                    };
+
+                                    dialog.Run();
+                                    dialog.Dispose();
+                                });
+                        }
+                    }
+
+                    fsClient.Unmount(source.ToU8Span());
+                    fsClient.Unmount(output.ToU8Span());
+                })
+                {
+                    Name = "GUI.NcaSectionExtractorThread",
+                    IsBackground = true,
+                };
+                extractorThread.Start();
+            }
+        }
+
+        private (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath)
+        {
+            Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath.ToU8Span(), OpenDirectoryMode.All);
+            if (rc.IsFailure())
+            {
+                return (rc, false);
+            }
+
+            using (sourceHandle)
+            {
+                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
+                {
+                    if (_cancel)
+                    {
+                        return (null, true);
+                    }
+
+                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
+                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));
+
+                    if (entry.Type == DirectoryEntryType.Directory)
+                    {
+                        fs.EnsureDirectoryExists(subDstPath);
+
+                        (Result? result, bool canceled) = CopyDirectory(fs, subSrcPath, subDstPath);
+                        if (canceled || result.Value.IsFailure())
+                        {
+                            return (result, canceled);
+                        }
+                    }
+
+                    if (entry.Type == DirectoryEntryType.File)
+                    {
+                        fs.CreateOrOverwriteFile(subDstPath, entry.Size);
+
+                        rc = CopyFile(fs, subSrcPath, subDstPath);
+                        if (rc.IsFailure())
+                        {
+                            return (rc, false);
+                        }
+                    }
+                }
+            }
+
+            return (Result.Success, false);
+        }
+
+        public static Result CopyFile(FileSystemClient fs, string sourcePath, string destPath)
+        {
+            Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath.ToU8Span(), OpenMode.Read);
+            if (rc.IsFailure())
+            {
+                return rc;
+            }
+
+            using (sourceHandle)
+            {
+                rc = fs.OpenFile(out FileHandle destHandle, destPath.ToU8Span(), OpenMode.Write | OpenMode.AllowAppend);
+                if (rc.IsFailure())
+                {
+                    return rc;
+                }
+
+                using (destHandle)
+                {
+                    const int MaxBufferSize = 1024 * 1024;
+
+                    rc = fs.GetFileSize(out long fileSize, sourceHandle);
+                    if (rc.IsFailure())
+                    {
+                        return rc;
+                    }
+
+                    int bufferSize = (int)Math.Min(MaxBufferSize, fileSize);
+
+                    byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
+                    try
+                    {
+                        for (long offset = 0; offset < fileSize; offset += bufferSize)
+                        {
+                            int toRead = (int)Math.Min(fileSize - offset, bufferSize);
+                            Span<byte> buf = buffer.AsSpan(0, toRead);
+
+                            rc = fs.ReadFile(out long _, sourceHandle, offset, buf);
+                            if (rc.IsFailure())
+                            {
+                                return rc;
+                            }
+
+                            rc = fs.WriteFile(destHandle, offset, buf, WriteOption.None);
+                            if (rc.IsFailure())
+                            {
+                                return rc;
+                            }
+                        }
+                    }
+                    finally
+                    {
+                        ArrayPool<byte>.Shared.Return(buffer);
+                    }
+
+                    rc = fs.FlushFile(destHandle);
+                    if (rc.IsFailure())
+                    {
+                        return rc;
+                    }
+                }
+            }
+
+            return Result.Success;
+        }
+
+        //
+        // Events
+        //
+        private void OpenSaveUserDir_Clicked(object sender, EventArgs args)
+        {
+            var userId = new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
+            var saveDataFilter = SaveDataFilter.Make(_titleId, saveType: default, userId, saveDataId: default, index: default);
+
+            OpenSaveDir(in saveDataFilter);
+        }
+
+        private void OpenSaveDeviceDir_Clicked(object sender, EventArgs args)
+        {
+            var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Device, userId: default, saveDataId: default, index: default);
+
+            OpenSaveDir(in saveDataFilter);
+        }
+
+        private void OpenSaveBcatDir_Clicked(object sender, EventArgs args)
+        {
+            var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
+
+            OpenSaveDir(in saveDataFilter);
+        }
+
+        private void ManageTitleUpdates_Clicked(object sender, EventArgs args)
+        {
+            new TitleUpdateWindow(_parent, _virtualFileSystem, _titleIdText, _titleName).Show();
+        }
+
+        private void ManageDlc_Clicked(object sender, EventArgs args)
+        {
+            new DlcWindow(_virtualFileSystem, _titleIdText, _titleName).Show();
+        }
+
+        private void ManageCheats_Clicked(object sender, EventArgs args)
+        {
+            new CheatWindow(_virtualFileSystem, _titleId, _titleName, _titleFilePath).Show();
+        }
+
+        private void OpenTitleModDir_Clicked(object sender, EventArgs args)
+        {
+            string modsBasePath = ModLoader.GetModsBasePath();
+            string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, _titleIdText);
+
+            OpenHelper.OpenFolder(titleModsPath);
+        }
+
+        private void OpenTitleSdModDir_Clicked(object sender, EventArgs args)
+        {
+            string sdModsBasePath = ModLoader.GetSdModsBasePath();
+            string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, _titleIdText);
+
+            OpenHelper.OpenFolder(titleModsPath);
+        }
+
+        private void ExtractRomFs_Clicked(object sender, EventArgs args)
+        {
+            ExtractSection(NcaSectionType.Data);
+        }
+
+        private void ExtractExeFs_Clicked(object sender, EventArgs args)
+        {
+            ExtractSection(NcaSectionType.Code);
+        }
+
+        private void ExtractLogo_Clicked(object sender, EventArgs args)
+        {
+            ExtractSection(NcaSectionType.Logo);
+        }
+
+        private void OpenPtcDir_Clicked(object sender, EventArgs args)
+        {
+            string ptcDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu");
+
+            string mainPath = System.IO.Path.Combine(ptcDir, "0");
+            string backupPath = System.IO.Path.Combine(ptcDir, "1");
+
+            if (!Directory.Exists(ptcDir))
+            {
+                Directory.CreateDirectory(ptcDir);
+                Directory.CreateDirectory(mainPath);
+                Directory.CreateDirectory(backupPath);
+            }
+
+            OpenHelper.OpenFolder(ptcDir);
+        }
+
+        private void OpenShaderCacheDir_Clicked(object sender, EventArgs args)
+        {
+            string shaderCacheDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader");
+
+            if (!Directory.Exists(shaderCacheDir))
+            {
+                Directory.CreateDirectory(shaderCacheDir);
+            }
+
+            OpenHelper.OpenFolder(shaderCacheDir);
+        }
+
+        private void PurgePtcCache_Clicked(object sender, EventArgs args)
+        {
+            DirectoryInfo mainDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "0"));
+            DirectoryInfo backupDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "1"));
+
+            MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to queue a PPTC rebuild on the next boot of:\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
+
+            List<FileInfo> cacheFiles = new();
+
+            if (mainDir.Exists)
+            {
+                cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache"));
+            }
+
+            if (backupDir.Exists)
+            {
+                cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
+            }
+
+            if (cacheFiles.Count > 0 && warningDialog.Run() == (int)ResponseType.Yes)
+            {
+                foreach (FileInfo file in cacheFiles)
+                {
+                    try
+                    {
+                        file.Delete();
+                    }
+                    catch (Exception e)
+                    {
+                        GtkDialog.CreateErrorDialog($"Error purging PPTC cache {file.Name}: {e}");
+                    }
+                }
+            }
+
+            warningDialog.Dispose();
+        }
+
+        private void PurgeShaderCache_Clicked(object sender, EventArgs args)
+        {
+            DirectoryInfo shaderCacheDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader"));
+
+            using MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to delete the shader cache for :\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
+
+            List<DirectoryInfo> oldCacheDirectories = new();
+            List<FileInfo> newCacheFiles = new();
+
+            if (shaderCacheDir.Exists)
+            {
+                oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*"));
+                newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc"));
+                newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data"));
+            }
+
+            if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0) && warningDialog.Run() == (int)ResponseType.Yes)
+            {
+                foreach (DirectoryInfo directory in oldCacheDirectories)
+                {
+                    try
+                    {
+                        directory.Delete(true);
+                    }
+                    catch (Exception e)
+                    {
+                        GtkDialog.CreateErrorDialog($"Error purging shader cache at {directory.Name}: {e}");
+                    }
+                }
+
+                foreach (FileInfo file in newCacheFiles)
+                {
+                    try
+                    {
+                        file.Delete();
+                    }
+                    catch (Exception e)
+                    {
+                        GtkDialog.CreateErrorDialog($"Error purging shader cache at {file.Name}: {e}");
+                    }
+                }
+            }
+        }
+
+        private void CreateShortcut_Clicked(object sender, EventArgs args)
+        {
+            byte[] appIcon = new ApplicationLibrary(_virtualFileSystem).GetApplicationIcon(_titleFilePath, ConfigurationState.Instance.System.Language);
+            ShortcutHelper.CreateAppShortcut(_titleFilePath, _titleName, _titleIdText, appIcon);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/GtkDialog.cs b/src/Ryujinx/UI/Widgets/GtkDialog.cs
new file mode 100644
index 00000000..567f9ad6
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/GtkDialog.cs
@@ -0,0 +1,114 @@
+using Gtk;
+using Ryujinx.Common.Logging;
+using Ryujinx.UI.Common.Configuration;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Ryujinx.UI.Widgets
+{
+    internal class GtkDialog : MessageDialog
+    {
+        private static bool _isChoiceDialogOpen;
+
+        private GtkDialog(string title, string mainText, string secondaryText, MessageType messageType = MessageType.Other, ButtonsType buttonsType = ButtonsType.Ok)
+            : base(null, DialogFlags.Modal, messageType, buttonsType, null)
+        {
+            Title = title;
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+            Text = mainText;
+            SecondaryText = secondaryText;
+            WindowPosition = WindowPosition.Center;
+            SecondaryUseMarkup = true;
+
+            Response += GtkDialog_Response;
+
+            SetSizeRequest(200, 20);
+        }
+
+        private void GtkDialog_Response(object sender, ResponseArgs args)
+        {
+            Dispose();
+        }
+
+        internal static void CreateInfoDialog(string mainText, string secondaryText)
+        {
+            new GtkDialog("Ryujinx - Info", mainText, secondaryText, MessageType.Info).Run();
+        }
+
+        internal static void CreateUpdaterInfoDialog(string mainText, string secondaryText)
+        {
+            new GtkDialog("Ryujinx - Updater", mainText, secondaryText, MessageType.Info).Run();
+        }
+
+        internal static MessageDialog CreateWaitingDialog(string mainText, string secondaryText)
+        {
+            return new GtkDialog("Ryujinx - Waiting", mainText, secondaryText, MessageType.Info, ButtonsType.None);
+        }
+
+        internal static void CreateWarningDialog(string mainText, string secondaryText)
+        {
+            new GtkDialog("Ryujinx - Warning", mainText, secondaryText, MessageType.Warning).Run();
+        }
+
+        internal static void CreateErrorDialog(string errorMessage)
+        {
+            Logger.Error?.Print(LogClass.Application, errorMessage);
+
+            new GtkDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage, MessageType.Error).Run();
+        }
+
+        internal static MessageDialog CreateConfirmationDialog(string mainText, string secondaryText = "")
+        {
+            return new GtkDialog("Ryujinx - Confirmation", mainText, secondaryText, MessageType.Question, ButtonsType.YesNo);
+        }
+
+        internal static bool CreateChoiceDialog(string title, string mainText, string secondaryText)
+        {
+            if (_isChoiceDialogOpen)
+            {
+                return false;
+            }
+
+            _isChoiceDialogOpen = true;
+
+            ResponseType response = (ResponseType)new GtkDialog(title, mainText, secondaryText, MessageType.Question, ButtonsType.YesNo).Run();
+
+            _isChoiceDialogOpen = false;
+
+            return response == ResponseType.Yes;
+        }
+
+        internal static ResponseType CreateCustomDialog(string title, string mainText, string secondaryText, Dictionary<int, string> buttons, MessageType messageType = MessageType.Other)
+        {
+            GtkDialog gtkDialog = new(title, mainText, secondaryText, messageType, ButtonsType.None);
+
+            foreach (var button in buttons)
+            {
+                gtkDialog.AddButton(button.Value, button.Key);
+            }
+
+            return (ResponseType)gtkDialog.Run();
+        }
+
+        internal static string CreateInputDialog(Window parent, string title, string mainText, uint inputMax)
+        {
+            GtkInputDialog gtkDialog = new(parent, title, mainText, inputMax);
+            ResponseType response = (ResponseType)gtkDialog.Run();
+            string responseText = gtkDialog.InputEntry.Text.TrimEnd();
+
+            gtkDialog.Dispose();
+
+            if (response == ResponseType.Ok)
+            {
+                return responseText;
+            }
+
+            return "";
+        }
+
+        internal static bool CreateExitDialog()
+        {
+            return CreateChoiceDialog("Ryujinx - Exit", "Are you sure you want to close Ryujinx?", "All unsaved data will be lost!");
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/GtkInputDialog.cs b/src/Ryujinx/UI/Widgets/GtkInputDialog.cs
new file mode 100644
index 00000000..fd85248b
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/GtkInputDialog.cs
@@ -0,0 +1,37 @@
+using Gtk;
+
+namespace Ryujinx.UI.Widgets
+{
+    public class GtkInputDialog : MessageDialog
+    {
+        public Entry InputEntry { get; }
+
+        public GtkInputDialog(Window parent, string title, string mainText, uint inputMax) : base(parent, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.OkCancel, null)
+        {
+            SetDefaultSize(300, 0);
+
+            Title = title;
+
+            Label mainTextLabel = new()
+            {
+                Text = mainText,
+            };
+
+            InputEntry = new Entry
+            {
+                MaxLength = (int)inputMax,
+            };
+
+            Label inputMaxTextLabel = new()
+            {
+                Text = $"(Max length: {inputMax})",
+            };
+
+            ((Box)MessageArea).PackStart(mainTextLabel, true, true, 0);
+            ((Box)MessageArea).PackStart(InputEntry, true, true, 5);
+            ((Box)MessageArea).PackStart(inputMaxTextLabel, true, true, 0);
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/ProfileDialog.cs b/src/Ryujinx/UI/Widgets/ProfileDialog.cs
new file mode 100644
index 00000000..f8aa6345
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/ProfileDialog.cs
@@ -0,0 +1,57 @@
+using Gtk;
+using Ryujinx.UI.Common.Configuration;
+using System;
+using System.Reflection;
+using GUI = Gtk.Builder.ObjectAttribute;
+
+namespace Ryujinx.UI.Widgets
+{
+    public class ProfileDialog : Dialog
+    {
+        public string FileName { get; private set; }
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] Entry _profileEntry;
+        [GUI] Label _errorMessage;
+#pragma warning restore CS0649, IDE0044
+
+        public ProfileDialog() : this(new Builder("Ryujinx.UI.Widgets.ProfileDialog.glade")) { }
+
+        private ProfileDialog(Builder builder) : base(builder.GetRawOwnedObject("_profileDialog"))
+        {
+            builder.Autoconnect(this);
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+        }
+
+        private void OkToggle_Activated(object sender, EventArgs args)
+        {
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+
+            bool validFileName = true;
+
+            foreach (char invalidChar in System.IO.Path.GetInvalidFileNameChars())
+            {
+                if (_profileEntry.Text.Contains(invalidChar))
+                {
+                    validFileName = false;
+                }
+            }
+
+            if (validFileName && !string.IsNullOrEmpty(_profileEntry.Text))
+            {
+                FileName = $"{_profileEntry.Text}.json";
+
+                Respond(ResponseType.Ok);
+            }
+            else
+            {
+                _errorMessage.Text = "The file name contains invalid characters. Please try again.";
+            }
+        }
+
+        private void CancelToggle_Activated(object sender, EventArgs args)
+        {
+            Respond(ResponseType.Cancel);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/ProfileDialog.glade b/src/Ryujinx/UI/Widgets/ProfileDialog.glade
new file mode 100644
index 00000000..adaf6608
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/ProfileDialog.glade
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="_profileDialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - Profile Dialog</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="default_width">400</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkToggleButton" id="OkToggle">
+                <property name="label" translatable="yes">OK</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="toggled" handler="OkToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToggleButton" id="CancelToggle">
+                <property name="label" translatable="yes">Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="toggled" handler="CancelToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">5</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="margin_top">20</property>
+                <property name="margin_bottom">10</property>
+                <property name="label" translatable="yes">Enter a name for the new profile:</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="_profileEntry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="margin_left">20</property>
+                <property name="margin_right">20</property>
+                <property name="margin_top">20</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="_errorMessage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="margin_left">20</property>
+                <property name="margin_right">10</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <attributes>
+                  <attribute name="foreground" value="#ffff00000000"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Widgets/RawInputToTextEntry.cs b/src/Ryujinx/UI/Widgets/RawInputToTextEntry.cs
new file mode 100644
index 00000000..6470790e
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/RawInputToTextEntry.cs
@@ -0,0 +1,27 @@
+using Gtk;
+
+namespace Ryujinx.UI.Widgets
+{
+    public class RawInputToTextEntry : Entry
+    {
+        public void SendKeyPressEvent(object o, KeyPressEventArgs args)
+        {
+            base.OnKeyPressEvent(args.Event);
+        }
+
+        public void SendKeyReleaseEvent(object o, KeyReleaseEventArgs args)
+        {
+            base.OnKeyReleaseEvent(args.Event);
+        }
+
+        public void SendButtonPressEvent(object o, ButtonPressEventArgs args)
+        {
+            base.OnButtonPressEvent(args.Event);
+        }
+
+        public void SendButtonReleaseEvent(object o, ButtonReleaseEventArgs args)
+        {
+            base.OnButtonReleaseEvent(args.Event);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Widgets/UserErrorDialog.cs b/src/Ryujinx/UI/Widgets/UserErrorDialog.cs
new file mode 100644
index 00000000..f0b55cd8
--- /dev/null
+++ b/src/Ryujinx/UI/Widgets/UserErrorDialog.cs
@@ -0,0 +1,123 @@
+using Gtk;
+using Ryujinx.UI.Common;
+using Ryujinx.UI.Common.Helper;
+
+namespace Ryujinx.UI.Widgets
+{
+    internal class UserErrorDialog : MessageDialog
+    {
+        private const string SetupGuideUrl = "https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide";
+        private const int OkResponseId = 0;
+        private const int SetupGuideResponseId = 1;
+
+        private readonly UserError _userError;
+
+        private UserErrorDialog(UserError error) : base(null, DialogFlags.Modal, MessageType.Error, ButtonsType.None, null)
+        {
+            _userError = error;
+
+            WindowPosition = WindowPosition.Center;
+            SecondaryUseMarkup = true;
+
+            Response += UserErrorDialog_Response;
+
+            SetSizeRequest(120, 50);
+
+            AddButton("OK", OkResponseId);
+
+            bool isInSetupGuide = IsCoveredBySetupGuide(error);
+
+            if (isInSetupGuide)
+            {
+                AddButton("Open the Setup Guide", SetupGuideResponseId);
+            }
+
+            string errorCode = GetErrorCode(error);
+
+            SecondaryUseMarkup = true;
+
+            Title = $"Ryujinx error ({errorCode})";
+            Text = $"{errorCode}: {GetErrorTitle(error)}";
+            SecondaryText = GetErrorDescription(error);
+
+            if (isInSetupGuide)
+            {
+                SecondaryText += "\n<b>For more information on how to fix this error, follow our Setup Guide.</b>";
+            }
+        }
+
+        private static string GetErrorCode(UserError error)
+        {
+            return $"RYU-{(uint)error:X4}";
+        }
+
+        private static string GetErrorTitle(UserError error)
+        {
+            return error switch
+            {
+                UserError.NoKeys => "Keys not found",
+                UserError.NoFirmware => "Firmware not found",
+                UserError.FirmwareParsingFailed => "Firmware parsing error",
+                UserError.ApplicationNotFound => "Application not found",
+                UserError.Unknown => "Unknown error",
+                _ => "Undefined error",
+            };
+        }
+
+        private static string GetErrorDescription(UserError error)
+        {
+            return error switch
+            {
+                UserError.NoKeys => "Ryujinx was unable to find your 'prod.keys' file",
+                UserError.NoFirmware => "Ryujinx was unable to find any firmwares installed",
+                UserError.FirmwareParsingFailed => "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
+                UserError.ApplicationNotFound => "Ryujinx couldn't find a valid application at the given path.",
+                UserError.Unknown => "An unknown error occured!",
+                _ => "An undefined error occured! This shouldn't happen, please contact a dev!",
+            };
+        }
+
+        private static bool IsCoveredBySetupGuide(UserError error)
+        {
+            return error switch
+            {
+                UserError.NoKeys or
+                UserError.NoFirmware or
+                UserError.FirmwareParsingFailed => true,
+                _ => false,
+            };
+        }
+
+        private static string GetSetupGuideUrl(UserError error)
+        {
+            if (!IsCoveredBySetupGuide(error))
+            {
+                return null;
+            }
+
+            return error switch
+            {
+                UserError.NoKeys => SetupGuideUrl + "#initial-setup---placement-of-prodkeys",
+                UserError.NoFirmware => SetupGuideUrl + "#initial-setup-continued---installation-of-firmware",
+                _ => SetupGuideUrl,
+            };
+        }
+
+        private void UserErrorDialog_Response(object sender, ResponseArgs args)
+        {
+            int responseId = (int)args.ResponseId;
+
+            if (responseId == SetupGuideResponseId)
+            {
+                OpenHelper.OpenUrl(GetSetupGuideUrl(_userError));
+            }
+
+            Dispose();
+        }
+
+        public static void CreateUserErrorDialog(UserError error)
+        {
+            new UserErrorDialog(error).Run();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/AboutWindow.Designer.cs b/src/Ryujinx/UI/Windows/AboutWindow.Designer.cs
new file mode 100644
index 00000000..fd912ef9
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/AboutWindow.Designer.cs
@@ -0,0 +1,511 @@
+using Gtk;
+using Pango;
+using Ryujinx.UI.Common.Configuration;
+using System.Reflection;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class AboutWindow : Window
+    {
+        private Box _mainBox;
+        private Box _leftBox;
+        private Box _logoBox;
+        private Image _ryujinxLogo;
+        private Box _logoTextBox;
+        private Label _ryujinxLabel;
+        private Label _ryujinxPhoneticLabel;
+        private EventBox _ryujinxLink;
+        private Label _ryujinxLinkLabel;
+        private Label _versionLabel;
+        private Label _disclaimerLabel;
+        private EventBox _amiiboApiLink;
+        private Label _amiiboApiLinkLabel;
+        private Box _socialBox;
+        private EventBox _patreonEventBox;
+        private Box _patreonBox;
+        private Image _patreonLogo;
+        private Label _patreonLabel;
+        private EventBox _githubEventBox;
+        private Box _githubBox;
+        private Image _githubLogo;
+        private Label _githubLabel;
+        private Box _discordBox;
+        private EventBox _discordEventBox;
+        private Image _discordLogo;
+        private Label _discordLabel;
+        private EventBox _twitterEventBox;
+        private Box _twitterBox;
+        private Image _twitterLogo;
+        private Label _twitterLabel;
+        private Separator _separator;
+        private Box _rightBox;
+        private Label _aboutLabel;
+        private Label _aboutDescriptionLabel;
+        private Label _createdByLabel;
+        private TextView _createdByText;
+        private EventBox _contributorsEventBox;
+        private Label _contributorsLinkLabel;
+        private Label _patreonNamesLabel;
+        private ScrolledWindow _patreonNamesScrolled;
+        private TextView _patreonNamesText;
+        private EventBox _changelogEventBox;
+        private Label _changelogLinkLabel;
+
+        private void InitializeComponent()
+        {
+
+            //
+            // AboutWindow
+            //
+            CanFocus = false;
+            Resizable = false;
+            Modal = true;
+            WindowPosition = WindowPosition.Center;
+            DefaultWidth = 800;
+            DefaultHeight = 450;
+            TypeHint = Gdk.WindowTypeHint.Dialog;
+
+            //
+            // _mainBox
+            //
+            _mainBox = new Box(Orientation.Horizontal, 0);
+
+            //
+            // _leftBox
+            //
+            _leftBox = new Box(Orientation.Vertical, 0)
+            {
+                Margin = 15,
+                MarginStart = 30,
+                MarginEnd = 0,
+            };
+
+            //
+            // _logoBox
+            //
+            _logoBox = new Box(Orientation.Horizontal, 0);
+
+            //
+            // _ryujinxLogo
+            //
+            _ryujinxLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png", 100, 100))
+            {
+                Margin = 10,
+                MarginStart = 15,
+            };
+
+            //
+            // _logoTextBox
+            //
+            _logoTextBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _ryujinxLabel
+            //
+            _ryujinxLabel = new Label("Ryujinx")
+            {
+                MarginTop = 15,
+                Justify = Justification.Center,
+                Attributes = new AttrList(),
+            };
+            _ryujinxLabel.Attributes.Insert(new Pango.AttrScale(2.7f));
+
+            //
+            // _ryujinxPhoneticLabel
+            //
+            _ryujinxPhoneticLabel = new Label("(REE-YOU-JINX)")
+            {
+                Justify = Justification.Center,
+            };
+
+            //
+            // _ryujinxLink
+            //
+            _ryujinxLink = new EventBox()
+            {
+                Margin = 5
+            };
+            _ryujinxLink.ButtonPressEvent += RyujinxButton_Pressed;
+
+            //
+            // _ryujinxLinkLabel
+            //
+            _ryujinxLinkLabel = new Label("www.ryujinx.org")
+            {
+                TooltipText = "Click to open the Ryujinx website in your default browser.",
+                Justify = Justification.Center,
+                Attributes = new AttrList(),
+            };
+            _ryujinxLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _versionLabel
+            //
+            _versionLabel = new Label(Program.Version)
+            {
+                Expand = true,
+                Justify = Justification.Center,
+                Margin = 5,
+            };
+
+            //
+            // _changelogEventBox
+            //
+            _changelogEventBox = new EventBox();
+            _changelogEventBox.ButtonPressEvent += ChangelogButton_Pressed;
+
+            //
+            // _changelogLinkLabel
+            //
+            _changelogLinkLabel = new Label("View Changelog on GitHub")
+            {
+                TooltipText = "Click to open the changelog for this version in your default browser.",
+                Justify = Justification.Center,
+                Attributes = new AttrList(),
+            };
+            _changelogLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _disclaimerLabel
+            //
+            _disclaimerLabel = new Label("Ryujinx is not affiliated with Nintendo™,\nor any of its partners, in any way.")
+            {
+                Expand = true,
+                Justify = Justification.Center,
+                Margin = 5,
+                Attributes = new AttrList(),
+            };
+            _disclaimerLabel.Attributes.Insert(new Pango.AttrScale(0.8f));
+
+            //
+            // _amiiboApiLink
+            //
+            _amiiboApiLink = new EventBox()
+            {
+                Margin = 5,
+            };
+            _amiiboApiLink.ButtonPressEvent += AmiiboApiButton_Pressed;
+
+            //
+            // _amiiboApiLinkLabel
+            //
+            _amiiboApiLinkLabel = new Label("AmiiboAPI (www.amiiboapi.com) is used\nin our Amiibo emulation.")
+            {
+                TooltipText = "Click to open the AmiiboAPI website in your default browser.",
+                Justify = Justification.Center,
+                Attributes = new AttrList(),
+            };
+            _amiiboApiLinkLabel.Attributes.Insert(new Pango.AttrScale(0.9f));
+
+            //
+            // _socialBox
+            //
+            _socialBox = new Box(Orientation.Horizontal, 0)
+            {
+                Margin = 25,
+                MarginBottom = 10,
+            };
+
+            //
+            // _patreonEventBox
+            //
+            _patreonEventBox = new EventBox()
+            {
+                TooltipText = "Click to open the Ryujinx Patreon page in your default browser.",
+            };
+            _patreonEventBox.ButtonPressEvent += PatreonButton_Pressed;
+
+            //
+            // _patreonBox
+            //
+            _patreonBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _patreonLogo
+            //
+            _patreonLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Patreon_Light.png", 30, 30))
+            {
+                Margin = 10,
+            };
+
+            //
+            // _patreonLabel
+            //
+            _patreonLabel = new Label("Patreon")
+            {
+                Justify = Justification.Center,
+            };
+
+            //
+            // _githubEventBox
+            //
+            _githubEventBox = new EventBox()
+            {
+                TooltipText = "Click to open the Ryujinx GitHub page in your default browser.",
+            };
+            _githubEventBox.ButtonPressEvent += GitHubButton_Pressed;
+
+            //
+            // _githubBox
+            //
+            _githubBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _githubLogo
+            //
+            _githubLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_GitHub_Light.png", 30, 30))
+            {
+                Margin = 10,
+            };
+
+            //
+            // _githubLabel
+            //
+            _githubLabel = new Label("GitHub")
+            {
+                Justify = Justification.Center,
+            };
+
+            //
+            // _discordBox
+            //
+            _discordBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _discordEventBox
+            //
+            _discordEventBox = new EventBox()
+            {
+                TooltipText = "Click to open an invite to the Ryujinx Discord server in your default browser.",
+            };
+            _discordEventBox.ButtonPressEvent += DiscordButton_Pressed;
+
+            //
+            // _discordLogo
+            //
+            _discordLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Discord_Light.png", 30, 30))
+            {
+                Margin = 10,
+            };
+
+            //
+            // _discordLabel
+            //
+            _discordLabel = new Label("Discord")
+            {
+                Justify = Justification.Center,
+            };
+
+            //
+            // _twitterEventBox
+            //
+            _twitterEventBox = new EventBox()
+            {
+                TooltipText = "Click to open the Ryujinx Twitter page in your default browser.",
+            };
+            _twitterEventBox.ButtonPressEvent += TwitterButton_Pressed;
+
+            //
+            // _twitterBox
+            //
+            _twitterBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _twitterLogo
+            //
+            _twitterLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Twitter_Light.png", 30, 30))
+            {
+                Margin = 10,
+            };
+
+            //
+            // _twitterLabel
+            //
+            _twitterLabel = new Label("Twitter")
+            {
+                Justify = Justification.Center,
+            };
+
+            //
+            // _separator
+            //
+            _separator = new Separator(Orientation.Vertical)
+            {
+                Margin = 15,
+            };
+
+            //
+            // _rightBox
+            //
+            _rightBox = new Box(Orientation.Vertical, 0)
+            {
+                Margin = 15,
+                MarginTop = 40,
+            };
+
+            //
+            // _aboutLabel
+            //
+            _aboutLabel = new Label("About :")
+            {
+                Halign = Align.Start,
+                Attributes = new AttrList(),
+            };
+            _aboutLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
+            _aboutLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _aboutDescriptionLabel
+            //
+            _aboutDescriptionLabel = new Label("Ryujinx is an emulator for the Nintendo Switch™.\n" +
+                                               "Please support us on Patreon.\n" +
+                                               "Get all the latest news on our Twitter or Discord.\n" +
+                                               "Developers interested in contributing can find out more on our GitHub or Discord.")
+            {
+                Margin = 15,
+                Halign = Align.Start,
+            };
+
+            //
+            // _createdByLabel
+            //
+            _createdByLabel = new Label("Maintained by :")
+            {
+                Halign = Align.Start,
+                Attributes = new AttrList(),
+            };
+            _createdByLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
+            _createdByLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _createdByText
+            //
+            _createdByText = new TextView()
+            {
+                WrapMode = Gtk.WrapMode.Word,
+                Editable = false,
+                CursorVisible = false,
+                Margin = 15,
+                MarginEnd = 30,
+            };
+            _createdByText.Buffer.Text = "gdkchan, Ac_K, Thog, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, Xpl0itR, GoffyDude, »jD« and more...";
+
+            //
+            // _contributorsEventBox
+            //
+            _contributorsEventBox = new EventBox();
+            _contributorsEventBox.ButtonPressEvent += ContributorsButton_Pressed;
+
+            //
+            // _contributorsLinkLabel
+            //
+            _contributorsLinkLabel = new Label("See All Contributors...")
+            {
+                TooltipText = "Click to open the Contributors page in your default browser.",
+                MarginEnd = 30,
+                Halign = Align.End,
+                Attributes = new AttrList(),
+            };
+            _contributorsLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _patreonNamesLabel
+            //
+            _patreonNamesLabel = new Label("Supported on Patreon by :")
+            {
+                Halign = Align.Start,
+                Attributes = new AttrList(),
+            };
+            _patreonNamesLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
+            _patreonNamesLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
+
+            //
+            // _patreonNamesScrolled
+            //
+            _patreonNamesScrolled = new ScrolledWindow()
+            {
+                Margin = 15,
+                MarginEnd = 30,
+                Expand = true,
+                ShadowType = ShadowType.In,
+            };
+            _patreonNamesScrolled.SetPolicy(PolicyType.Never, PolicyType.Automatic);
+
+            //
+            // _patreonNamesText
+            //
+            _patreonNamesText = new TextView()
+            {
+                WrapMode = Gtk.WrapMode.Word,
+            };
+            _patreonNamesText.Buffer.Text = "Loading...";
+            _patreonNamesText.SetProperty("editable", new GLib.Value(false));
+
+            ShowComponent();
+        }
+
+        private void ShowComponent()
+        {
+            _logoBox.Add(_ryujinxLogo);
+
+            _ryujinxLink.Add(_ryujinxLinkLabel);
+
+            _logoTextBox.Add(_ryujinxLabel);
+            _logoTextBox.Add(_ryujinxPhoneticLabel);
+            _logoTextBox.Add(_ryujinxLink);
+
+            _logoBox.Add(_logoTextBox);
+
+            _amiiboApiLink.Add(_amiiboApiLinkLabel);
+
+            _patreonBox.Add(_patreonLogo);
+            _patreonBox.Add(_patreonLabel);
+            _patreonEventBox.Add(_patreonBox);
+
+            _githubBox.Add(_githubLogo);
+            _githubBox.Add(_githubLabel);
+            _githubEventBox.Add(_githubBox);
+
+            _discordBox.Add(_discordLogo);
+            _discordBox.Add(_discordLabel);
+            _discordEventBox.Add(_discordBox);
+
+            _twitterBox.Add(_twitterLogo);
+            _twitterBox.Add(_twitterLabel);
+            _twitterEventBox.Add(_twitterBox);
+
+            _socialBox.Add(_patreonEventBox);
+            _socialBox.Add(_githubEventBox);
+            _socialBox.Add(_discordEventBox);
+            _socialBox.Add(_twitterEventBox);
+
+            _changelogEventBox.Add(_changelogLinkLabel);
+
+            _leftBox.Add(_logoBox);
+            _leftBox.Add(_versionLabel);
+            _leftBox.Add(_changelogEventBox);
+            _leftBox.Add(_disclaimerLabel);
+            _leftBox.Add(_amiiboApiLink);
+            _leftBox.Add(_socialBox);
+
+            _contributorsEventBox.Add(_contributorsLinkLabel);
+            _patreonNamesScrolled.Add(_patreonNamesText);
+
+            _rightBox.Add(_aboutLabel);
+            _rightBox.Add(_aboutDescriptionLabel);
+            _rightBox.Add(_createdByLabel);
+            _rightBox.Add(_createdByText);
+            _rightBox.Add(_contributorsEventBox);
+            _rightBox.Add(_patreonNamesLabel);
+            _rightBox.Add(_patreonNamesScrolled);
+
+            _mainBox.Add(_leftBox);
+            _mainBox.Add(_separator);
+            _mainBox.Add(_rightBox);
+
+            Add(_mainBox);
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/AboutWindow.cs b/src/Ryujinx/UI/Windows/AboutWindow.cs
new file mode 100644
index 00000000..f4bb533c
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/AboutWindow.cs
@@ -0,0 +1,85 @@
+using Gtk;
+using Ryujinx.Common.Utilities;
+using Ryujinx.UI.Common.Helper;
+using System.Net.Http;
+using System.Net.NetworkInformation;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class AboutWindow : Window
+    {
+        public AboutWindow() : base($"Ryujinx {Program.Version} - About")
+        {
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(OpenHelper)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+            InitializeComponent();
+
+            _ = DownloadPatronsJson();
+        }
+
+        private async Task DownloadPatronsJson()
+        {
+            if (!NetworkInterface.GetIsNetworkAvailable())
+            {
+                _patreonNamesText.Buffer.Text = "Connection Error.";
+            }
+
+            HttpClient httpClient = new();
+
+            try
+            {
+                string patreonJsonString = await httpClient.GetStringAsync("https://patreon.ryujinx.org/");
+
+                _patreonNamesText.Buffer.Text = string.Join(", ", JsonHelper.Deserialize(patreonJsonString, CommonJsonContext.Default.StringArray));
+            }
+            catch
+            {
+                _patreonNamesText.Buffer.Text = "API Error.";
+            }
+        }
+
+        //
+        // Events
+        //
+        private void RyujinxButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://ryujinx.org");
+        }
+
+        private void AmiiboApiButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://amiiboapi.com");
+        }
+
+        private void PatreonButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://www.patreon.com/ryujinx");
+        }
+
+        private void GitHubButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx");
+        }
+
+        private void DiscordButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://discordapp.com/invite/N2FmfVc");
+        }
+
+        private void TwitterButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://twitter.com/RyujinxEmu");
+        }
+
+        private void ContributorsButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx/graphs/contributors?type=a");
+        }
+
+        private void ChangelogButton_Pressed(object sender, ButtonPressEventArgs args)
+        {
+            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx/wiki/Changelog#ryujinx-changelog");
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/AmiiboWindow.Designer.cs b/src/Ryujinx/UI/Windows/AmiiboWindow.Designer.cs
new file mode 100644
index 00000000..3bf73318
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/AmiiboWindow.Designer.cs
@@ -0,0 +1,190 @@
+using Gtk;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class AmiiboWindow : Window
+    {
+        private Box _mainBox;
+        private ButtonBox _buttonBox;
+        private Button _scanButton;
+        private Button _cancelButton;
+        private CheckButton _randomUuidCheckBox;
+        private Box _amiiboBox;
+        private Box _amiiboHeadBox;
+        private Box _amiiboSeriesBox;
+        private Label _amiiboSeriesLabel;
+        private ComboBoxText _amiiboSeriesComboBox;
+        private Box _amiiboCharsBox;
+        private Label _amiiboCharsLabel;
+        private ComboBoxText _amiiboCharsComboBox;
+        private CheckButton _showAllCheckBox;
+        private Image _amiiboImage;
+        private Label _gameUsageLabel;
+
+        private void InitializeComponent()
+        {
+            //
+            // AmiiboWindow
+            //
+            CanFocus = false;
+            Resizable = false;
+            Modal = true;
+            WindowPosition = WindowPosition.Center;
+            DefaultWidth = 600;
+            DefaultHeight = 470;
+            TypeHint = Gdk.WindowTypeHint.Dialog;
+
+            //
+            // _mainBox
+            //
+            _mainBox = new Box(Orientation.Vertical, 2);
+
+            //
+            // _buttonBox
+            //
+            _buttonBox = new ButtonBox(Orientation.Horizontal)
+            {
+                Margin = 20,
+                LayoutStyle = ButtonBoxStyle.End,
+            };
+
+            //
+            // _scanButton
+            //
+            _scanButton = new Button()
+            {
+                Label = "Scan It!",
+                CanFocus = true,
+                ReceivesDefault = true,
+                MarginStart = 10,
+            };
+            _scanButton.Clicked += ScanButton_Pressed;
+
+            //
+            // _randomUuidCheckBox
+            //
+            _randomUuidCheckBox = new CheckButton()
+            {
+                Label = "Hack: Use Random Tag Uuid",
+                TooltipText = "This allows multiple scans of a single Amiibo.\n(used in The Legend of Zelda: Breath of the Wild)",
+            };
+
+            //
+            // _cancelButton
+            //
+            _cancelButton = new Button()
+            {
+                Label = "Cancel",
+                CanFocus = true,
+                ReceivesDefault = true,
+                MarginStart = 10,
+            };
+            _cancelButton.Clicked += CancelButton_Pressed;
+
+            //
+            // _amiiboBox
+            //
+            _amiiboBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _amiiboHeadBox
+            //
+            _amiiboHeadBox = new Box(Orientation.Horizontal, 0)
+            {
+                Margin = 20,
+                Hexpand = true,
+            };
+
+            //
+            // _amiiboSeriesBox
+            //
+            _amiiboSeriesBox = new Box(Orientation.Horizontal, 0)
+            {
+                Hexpand = true,
+            };
+
+            //
+            // _amiiboSeriesLabel
+            //
+            _amiiboSeriesLabel = new Label("Amiibo Series:");
+
+            //
+            // _amiiboSeriesComboBox
+            //
+            _amiiboSeriesComboBox = new ComboBoxText();
+
+            //
+            // _amiiboCharsBox
+            //
+            _amiiboCharsBox = new Box(Orientation.Horizontal, 0)
+            {
+                Hexpand = true,
+            };
+
+            //
+            // _amiiboCharsLabel
+            //
+            _amiiboCharsLabel = new Label("Character:");
+
+            //
+            // _amiiboCharsComboBox
+            //
+            _amiiboCharsComboBox = new ComboBoxText();
+
+            //
+            // _showAllCheckBox
+            //
+            _showAllCheckBox = new CheckButton()
+            {
+                Label = "Show All Amiibo",
+            };
+
+            //
+            // _amiiboImage
+            //
+            _amiiboImage = new Image()
+            {
+                HeightRequest = 350,
+                WidthRequest = 350,
+            };
+
+            //
+            // _gameUsageLabel
+            //
+            _gameUsageLabel = new Label("")
+            {
+                MarginTop = 20,
+            };
+
+            ShowComponent();
+        }
+
+        private void ShowComponent()
+        {
+            _buttonBox.Add(_showAllCheckBox);
+            _buttonBox.Add(_randomUuidCheckBox);
+            _buttonBox.Add(_scanButton);
+            _buttonBox.Add(_cancelButton);
+
+            _amiiboSeriesBox.Add(_amiiboSeriesLabel);
+            _amiiboSeriesBox.Add(_amiiboSeriesComboBox);
+
+            _amiiboCharsBox.Add(_amiiboCharsLabel);
+            _amiiboCharsBox.Add(_amiiboCharsComboBox);
+
+            _amiiboHeadBox.Add(_amiiboSeriesBox);
+            _amiiboHeadBox.Add(_amiiboCharsBox);
+
+            _amiiboBox.PackStart(_amiiboHeadBox, true, true, 0);
+            _amiiboBox.PackEnd(_gameUsageLabel, false, false, 0);
+            _amiiboBox.PackEnd(_amiiboImage, false, false, 0);
+
+            _mainBox.Add(_amiiboBox);
+            _mainBox.PackEnd(_buttonBox, false, false, 0);
+
+            Add(_mainBox);
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/AmiiboWindow.cs b/src/Ryujinx/UI/Windows/AmiiboWindow.cs
new file mode 100644
index 00000000..d8c0b0c0
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/AmiiboWindow.cs
@@ -0,0 +1,438 @@
+using Gdk;
+using Gtk;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Models.Amiibo;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Reflection;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Window = Gtk.Window;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class AmiiboWindow : Window
+    {
+        private const string DefaultJson = "{ \"amiibo\": [] }";
+
+        public string AmiiboId { get; private set; }
+
+        public int DeviceId { get; set; }
+        public string TitleId { get; set; }
+        public string LastScannedAmiiboId { get; set; }
+        public bool LastScannedAmiiboShowAll { get; set; }
+
+        public ResponseType Response { get; private set; }
+
+        public bool UseRandomUuid
+        {
+            get
+            {
+                return _randomUuidCheckBox.Active;
+            }
+        }
+
+        private readonly HttpClient _httpClient;
+        private readonly string _amiiboJsonPath;
+
+        private readonly byte[] _amiiboLogoBytes;
+
+        private List<AmiiboApi> _amiiboList;
+
+        private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+        public AmiiboWindow() : base($"Ryujinx {Program.Version} - Amiibo")
+        {
+            Icon = new Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            InitializeComponent();
+
+            _httpClient = new HttpClient
+            {
+                Timeout = TimeSpan.FromSeconds(30),
+            };
+
+            Directory.CreateDirectory(System.IO.Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
+
+            _amiiboJsonPath = System.IO.Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", "Amiibo.json");
+            _amiiboList = new List<AmiiboApi>();
+
+            _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png");
+            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
+
+            _scanButton.Sensitive = false;
+            _randomUuidCheckBox.Sensitive = false;
+
+            _ = LoadContentAsync();
+        }
+
+        private static bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
+        {
+            if (string.IsNullOrEmpty(json))
+            {
+                amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
+
+                return false;
+            }
+
+            try
+            {
+                amiiboJson = JsonHelper.Deserialize(json, _serializerContext.AmiiboJson);
+
+                return true;
+            }
+            catch (JsonException exception)
+            {
+                Logger.Error?.Print(LogClass.Application, $"Unable to deserialize amiibo data: {exception}");
+                amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
+
+                return false;
+            }
+        }
+
+        private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
+        {
+            bool localIsValid = false;
+            bool remoteIsValid = false;
+            AmiiboJson amiiboJson = new();
+
+            try
+            {
+                try
+                {
+                    if (File.Exists(_amiiboJsonPath))
+                    {
+                        localIsValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson);
+                    }
+                }
+                catch (Exception exception)
+                {
+                    Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
+                }
+
+                if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
+                {
+                    remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
+                }
+            }
+            catch (Exception exception)
+            {
+                if (!(localIsValid || remoteIsValid))
+                {
+                    Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
+
+                    // Neither local or remote files are valid JSON, close window.
+                    ShowInfoDialog();
+                    Close();
+                }
+                else if (!remoteIsValid)
+                {
+                    Logger.Warning?.Print(LogClass.Application, $"Couldn't update amiibo data: {exception}");
+
+                    // Only the local file is valid, the local one should be used
+                    // but the user should be warned.
+                    ShowInfoDialog();
+                }
+            }
+
+            return amiiboJson;
+        }
+
+        private async Task LoadContentAsync()
+        {
+            AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
+
+            _amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
+
+            if (LastScannedAmiiboShowAll)
+            {
+                _showAllCheckBox.Click();
+            }
+
+            ParseAmiiboData();
+
+            _showAllCheckBox.Clicked += ShowAllCheckBox_Clicked;
+        }
+
+        private void ParseAmiiboData()
+        {
+            List<string> comboxItemList = new();
+
+            for (int i = 0; i < _amiiboList.Count; i++)
+            {
+                if (!comboxItemList.Contains(_amiiboList[i].AmiiboSeries))
+                {
+                    if (!_showAllCheckBox.Active)
+                    {
+                        foreach (var game in _amiiboList[i].GamesSwitch)
+                        {
+                            if (game != null)
+                            {
+                                if (game.GameId.Contains(TitleId))
+                                {
+                                    comboxItemList.Add(_amiiboList[i].AmiiboSeries);
+                                    _amiiboSeriesComboBox.Append(_amiiboList[i].AmiiboSeries, _amiiboList[i].AmiiboSeries);
+
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        comboxItemList.Add(_amiiboList[i].AmiiboSeries);
+                        _amiiboSeriesComboBox.Append(_amiiboList[i].AmiiboSeries, _amiiboList[i].AmiiboSeries);
+                    }
+                }
+            }
+
+            _amiiboSeriesComboBox.Changed += SeriesComboBox_Changed;
+            _amiiboCharsComboBox.Changed += CharacterComboBox_Changed;
+
+            if (LastScannedAmiiboId != "")
+            {
+                SelectLastScannedAmiibo();
+            }
+            else
+            {
+                _amiiboSeriesComboBox.Active = 0;
+            }
+        }
+
+        private void SelectLastScannedAmiibo()
+        {
+            bool isSet = _amiiboSeriesComboBox.SetActiveId(_amiiboList.Find(amiibo => amiibo.Head + amiibo.Tail == LastScannedAmiiboId).AmiiboSeries);
+            isSet = _amiiboCharsComboBox.SetActiveId(LastScannedAmiiboId);
+
+            if (isSet == false)
+            {
+                _amiiboSeriesComboBox.Active = 0;
+            }
+        }
+
+        private async Task<bool> NeedsUpdate(DateTime oldLastModified)
+        {
+            try
+            {
+                HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
+
+                if (response.IsSuccessStatusCode)
+                {
+                    return response.Content.Headers.LastModified != oldLastModified;
+                }
+            }
+            catch (HttpRequestException exception)
+            {
+                Logger.Error?.Print(LogClass.Application, $"Unable to check for amiibo data updates: {exception}");
+            }
+
+            return false;
+        }
+
+        private async Task<string> DownloadAmiiboJson()
+        {
+            try
+            {
+                HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
+
+                if (response.IsSuccessStatusCode)
+                {
+                    string amiiboJsonString = await response.Content.ReadAsStringAsync();
+
+                    try
+                    {
+                        using FileStream dlcJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough);
+                        dlcJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
+                    }
+                    catch (Exception exception)
+                    {
+                        Logger.Warning?.Print(LogClass.Application, $"Couldn't write amiibo data to file '{_amiiboJsonPath}: {exception}'");
+                    }
+
+                    return amiiboJsonString;
+                }
+
+                Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
+            }
+            catch (HttpRequestException exception)
+            {
+                Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}");
+            }
+
+            GtkDialog.CreateInfoDialog("Amiibo API", "An error occured while fetching information from the API.");
+
+            return null;
+        }
+
+        private async Task UpdateAmiiboPreview(string imageUrl)
+        {
+            HttpResponseMessage response = await _httpClient.GetAsync(imageUrl);
+
+            if (response.IsSuccessStatusCode)
+            {
+                byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync();
+                Pixbuf amiiboPreview = new(amiiboPreviewBytes);
+
+                float ratio = Math.Min((float)_amiiboImage.AllocatedWidth / amiiboPreview.Width,
+                                       (float)_amiiboImage.AllocatedHeight / amiiboPreview.Height);
+
+                int resizeHeight = (int)(amiiboPreview.Height * ratio);
+                int resizeWidth = (int)(amiiboPreview.Width * ratio);
+
+                _amiiboImage.Pixbuf = amiiboPreview.ScaleSimple(resizeWidth, resizeHeight, InterpType.Bilinear);
+            }
+            else
+            {
+                Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}");
+            }
+        }
+
+        private static void ShowInfoDialog()
+        {
+            GtkDialog.CreateInfoDialog("Amiibo API", "Unable to connect to Amiibo API server. The service may be down or you may need to verify your internet connection is online.");
+        }
+
+        //
+        // Events
+        //
+        private void SeriesComboBox_Changed(object sender, EventArgs args)
+        {
+            _amiiboCharsComboBox.Changed -= CharacterComboBox_Changed;
+
+            _amiiboCharsComboBox.RemoveAll();
+
+            List<AmiiboApi> amiiboSortedList = _amiiboList.Where(amiibo => amiibo.AmiiboSeries == _amiiboSeriesComboBox.ActiveId).OrderBy(amiibo => amiibo.Name).ToList();
+
+            List<string> comboxItemList = new();
+
+            for (int i = 0; i < amiiboSortedList.Count; i++)
+            {
+                if (!comboxItemList.Contains(amiiboSortedList[i].Head + amiiboSortedList[i].Tail))
+                {
+                    if (!_showAllCheckBox.Active)
+                    {
+                        foreach (var game in amiiboSortedList[i].GamesSwitch)
+                        {
+                            if (game != null)
+                            {
+                                if (game.GameId.Contains(TitleId))
+                                {
+                                    comboxItemList.Add(amiiboSortedList[i].Head + amiiboSortedList[i].Tail);
+                                    _amiiboCharsComboBox.Append(amiiboSortedList[i].Head + amiiboSortedList[i].Tail, amiiboSortedList[i].Name);
+
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        comboxItemList.Add(amiiboSortedList[i].Head + amiiboSortedList[i].Tail);
+                        _amiiboCharsComboBox.Append(amiiboSortedList[i].Head + amiiboSortedList[i].Tail, amiiboSortedList[i].Name);
+                    }
+                }
+            }
+
+            _amiiboCharsComboBox.Changed += CharacterComboBox_Changed;
+
+            _amiiboCharsComboBox.Active = 0;
+
+            _scanButton.Sensitive = true;
+            _randomUuidCheckBox.Sensitive = true;
+        }
+
+        private void CharacterComboBox_Changed(object sender, EventArgs args)
+        {
+            AmiiboId = _amiiboCharsComboBox.ActiveId;
+
+            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
+
+            string imageUrl = _amiiboList.Find(amiibo => amiibo.Head + amiibo.Tail == _amiiboCharsComboBox.ActiveId).Image;
+
+            var usageStringBuilder = new StringBuilder();
+
+            for (int i = 0; i < _amiiboList.Count; i++)
+            {
+                if (_amiiboList[i].Head + _amiiboList[i].Tail == _amiiboCharsComboBox.ActiveId)
+                {
+                    bool writable = false;
+
+                    foreach (var item in _amiiboList[i].GamesSwitch)
+                    {
+                        if (item.GameId.Contains(TitleId))
+                        {
+                            foreach (AmiiboApiUsage usageItem in item.AmiiboUsage)
+                            {
+                                usageStringBuilder.Append(Environment.NewLine);
+                                usageStringBuilder.Append($"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
+
+                                writable = usageItem.Write;
+                            }
+                        }
+                    }
+
+                    if (usageStringBuilder.Length == 0)
+                    {
+                        usageStringBuilder.Append("Unknown.");
+                    }
+
+                    _gameUsageLabel.Text = $"Usage{(writable ? " (Writable)" : "")} : {usageStringBuilder}";
+                }
+            }
+
+            _ = UpdateAmiiboPreview(imageUrl);
+        }
+
+        private void ShowAllCheckBox_Clicked(object sender, EventArgs e)
+        {
+            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
+
+            _amiiboSeriesComboBox.Changed -= SeriesComboBox_Changed;
+            _amiiboCharsComboBox.Changed -= CharacterComboBox_Changed;
+
+            _amiiboSeriesComboBox.RemoveAll();
+            _amiiboCharsComboBox.RemoveAll();
+
+            _scanButton.Sensitive = false;
+            _randomUuidCheckBox.Sensitive = false;
+
+            new Task(ParseAmiiboData).Start();
+        }
+
+        private void ScanButton_Pressed(object sender, EventArgs args)
+        {
+            LastScannedAmiiboShowAll = _showAllCheckBox.Active;
+
+            Response = ResponseType.Ok;
+
+            Close();
+        }
+
+        private void CancelButton_Pressed(object sender, EventArgs args)
+        {
+            AmiiboId = "";
+            LastScannedAmiiboId = "";
+            LastScannedAmiiboShowAll = false;
+
+            Response = ResponseType.Cancel;
+
+            Close();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            _httpClient.Dispose();
+
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/AvatarWindow.cs b/src/Ryujinx/UI/Windows/AvatarWindow.cs
new file mode 100644
index 00000000..7cddc362
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/AvatarWindow.cs
@@ -0,0 +1,291 @@
+using Gtk;
+using LibHac.Common;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.FsSystem;
+using LibHac.Ncm;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.UI.Common.Configuration;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Image = SixLabors.ImageSharp.Image;
+
+namespace Ryujinx.UI.Windows
+{
+    public class AvatarWindow : Window
+    {
+        public byte[] SelectedProfileImage;
+        public bool NewUser;
+
+        private static readonly Dictionary<string, byte[]> _avatarDict = new();
+
+        private readonly ListStore _listStore;
+        private readonly IconView _iconView;
+        private readonly Button _setBackgroungColorButton;
+        private Gdk.RGBA _backgroundColor;
+
+        public AvatarWindow() : base($"Ryujinx {Program.Version} - Manage Accounts - Avatar")
+        {
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            CanFocus = false;
+            Resizable = false;
+            Modal = true;
+            TypeHint = Gdk.WindowTypeHint.Dialog;
+
+            SetDefaultSize(740, 400);
+            SetPosition(WindowPosition.Center);
+
+            Box vbox = new(Orientation.Vertical, 0);
+            Add(vbox);
+
+            ScrolledWindow scrolledWindow = new()
+            {
+                ShadowType = ShadowType.EtchedIn,
+            };
+            scrolledWindow.SetPolicy(PolicyType.Automatic, PolicyType.Automatic);
+
+            Box hbox = new(Orientation.Horizontal, 0);
+
+            Button chooseButton = new()
+            {
+                Label = "Choose",
+                CanFocus = true,
+                ReceivesDefault = true,
+            };
+            chooseButton.Clicked += ChooseButton_Pressed;
+
+            _setBackgroungColorButton = new Button()
+            {
+                Label = "Set Background Color",
+                CanFocus = true,
+            };
+            _setBackgroungColorButton.Clicked += SetBackgroungColorButton_Pressed;
+
+            _backgroundColor.Red = 1;
+            _backgroundColor.Green = 1;
+            _backgroundColor.Blue = 1;
+            _backgroundColor.Alpha = 1;
+
+            Button closeButton = new()
+            {
+                Label = "Close",
+                CanFocus = true,
+            };
+            closeButton.Clicked += CloseButton_Pressed;
+
+            vbox.PackStart(scrolledWindow, true, true, 0);
+            hbox.PackStart(chooseButton, true, true, 0);
+            hbox.PackStart(_setBackgroungColorButton, true, true, 0);
+            hbox.PackStart(closeButton, true, true, 0);
+            vbox.PackStart(hbox, false, false, 0);
+
+            _listStore = new ListStore(typeof(string), typeof(Gdk.Pixbuf));
+            _listStore.SetSortColumnId(0, SortType.Ascending);
+
+            _iconView = new IconView(_listStore)
+            {
+                ItemWidth = 64,
+                ItemPadding = 10,
+                PixbufColumn = 1,
+            };
+
+            _iconView.SelectionChanged += IconView_SelectionChanged;
+
+            scrolledWindow.Add(_iconView);
+
+            _iconView.GrabFocus();
+
+            ProcessAvatars();
+
+            ShowAll();
+        }
+
+        public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
+        {
+            if (_avatarDict.Count > 0)
+            {
+                return;
+            }
+
+            string contentPath = contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem, NcaContentType.Data);
+            string avatarPath = VirtualFileSystem.SwitchPathToSystemPath(contentPath);
+
+            if (!string.IsNullOrWhiteSpace(avatarPath))
+            {
+                using IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open);
+
+                Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
+                IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
+
+                foreach (var item in romfs.EnumerateEntries())
+                {
+                    // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
+
+                    if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
+                    {
+                        using var file = new UniqueRef<IFile>();
+
+                        romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                        using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
+                        using MemoryStream streamPng = MemoryStreamManager.Shared.GetStream();
+                        file.Get.AsStream().CopyTo(stream);
+
+                        stream.Position = 0;
+
+                        Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
+
+                        avatarImage.SaveAsPng(streamPng);
+
+                        _avatarDict.Add(item.FullPath, streamPng.ToArray());
+                    }
+                }
+            }
+        }
+
+        private void ProcessAvatars()
+        {
+            _listStore.Clear();
+
+            foreach (var avatar in _avatarDict)
+            {
+                _listStore.AppendValues(avatar.Key, new Gdk.Pixbuf(ProcessImage(avatar.Value), 96, 96));
+            }
+
+            _iconView.SelectPath(new TreePath(new[] { 0 }));
+        }
+
+        private byte[] ProcessImage(byte[] data)
+        {
+            using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
+
+            Image avatarImage = Image.Load(data, new PngDecoder());
+
+            avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(
+                (byte)(_backgroundColor.Red * 255),
+                (byte)(_backgroundColor.Green * 255),
+                (byte)(_backgroundColor.Blue * 255),
+                (byte)(_backgroundColor.Alpha * 255)
+            )));
+            avatarImage.SaveAsJpeg(streamJpg);
+
+            return streamJpg.ToArray();
+        }
+
+        private void CloseButton_Pressed(object sender, EventArgs e)
+        {
+            SelectedProfileImage = null;
+
+            Close();
+        }
+
+        private void IconView_SelectionChanged(object sender, EventArgs e)
+        {
+            if (_iconView.SelectedItems.Length > 0)
+            {
+                _listStore.GetIter(out TreeIter iter, _iconView.SelectedItems[0]);
+
+                SelectedProfileImage = ProcessImage(_avatarDict[(string)_listStore.GetValue(iter, 0)]);
+            }
+        }
+
+        private void SetBackgroungColorButton_Pressed(object sender, EventArgs e)
+        {
+            using ColorChooserDialog colorChooserDialog = new("Set Background Color", this);
+
+            colorChooserDialog.UseAlpha = false;
+            colorChooserDialog.Rgba = _backgroundColor;
+
+            if (colorChooserDialog.Run() == (int)ResponseType.Ok)
+            {
+                _backgroundColor = colorChooserDialog.Rgba;
+
+                ProcessAvatars();
+            }
+
+            colorChooserDialog.Hide();
+        }
+
+        private void ChooseButton_Pressed(object sender, EventArgs e)
+        {
+            Close();
+        }
+
+        private static byte[] DecompressYaz0(Stream stream)
+        {
+            using BinaryReader reader = new(stream);
+
+            reader.ReadInt32(); // Magic
+
+            uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
+
+            reader.ReadInt64(); // Padding
+
+            byte[] input = new byte[stream.Length - stream.Position];
+            stream.Read(input, 0, input.Length);
+
+            long inputOffset = 0;
+
+            byte[] output = new byte[decodedLength];
+            long outputOffset = 0;
+
+            ushort mask = 0;
+            byte header = 0;
+
+            while (outputOffset < decodedLength)
+            {
+                if ((mask >>= 1) == 0)
+                {
+                    header = input[inputOffset++];
+                    mask = 0x80;
+                }
+
+                if ((header & mask) > 0)
+                {
+                    if (outputOffset == output.Length)
+                    {
+                        break;
+                    }
+
+                    output[outputOffset++] = input[inputOffset++];
+                }
+                else
+                {
+                    byte byte1 = input[inputOffset++];
+                    byte byte2 = input[inputOffset++];
+
+                    int dist = ((byte1 & 0xF) << 8) | byte2;
+                    int position = (int)outputOffset - (dist + 1);
+
+                    int length = byte1 >> 4;
+                    if (length == 0)
+                    {
+                        length = input[inputOffset++] + 0x12;
+                    }
+                    else
+                    {
+                        length += 2;
+                    }
+
+                    while (length-- > 0)
+                    {
+                        output[outputOffset++] = output[position++];
+                    }
+                }
+            }
+
+            return output;
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/CheatWindow.cs b/src/Ryujinx/UI/Windows/CheatWindow.cs
new file mode 100644
index 00000000..73ee870c
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/CheatWindow.cs
@@ -0,0 +1,156 @@
+using Gtk;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS;
+using Ryujinx.UI.App.Common;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using GUI = Gtk.Builder.ObjectAttribute;
+
+namespace Ryujinx.UI.Windows
+{
+    public class CheatWindow : Window
+    {
+        private readonly string _enabledCheatsPath;
+        private readonly bool _noCheatsFound;
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] Label _baseTitleInfoLabel;
+        [GUI] TextView _buildIdTextView;
+        [GUI] TreeView _cheatTreeView;
+        [GUI] Button _saveButton;
+#pragma warning restore CS0649, IDE0044
+
+        public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : this(new Builder("Ryujinx.UI.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName, titlePath) { }
+
+        private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : base(builder.GetRawOwnedObject("_cheatWindow"))
+        {
+            builder.Autoconnect(this);
+            _baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
+            _buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath)}";
+
+            string modsBasePath = ModLoader.GetModsBasePath();
+            string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, titleId.ToString("X16"));
+
+            _enabledCheatsPath = System.IO.Path.Combine(titleModsPath, "cheats", "enabled.txt");
+
+            _cheatTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string), typeof(string));
+
+            CellRendererToggle enableToggle = new();
+            enableToggle.Toggled += (sender, args) =>
+            {
+                _cheatTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
+                bool newValue = !(bool)_cheatTreeView.Model.GetValue(treeIter, 0);
+                _cheatTreeView.Model.SetValue(treeIter, 0, newValue);
+
+                if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
+                {
+                    do
+                    {
+                        _cheatTreeView.Model.SetValue(childIter, 0, newValue);
+                    }
+                    while (_cheatTreeView.Model.IterNext(ref childIter));
+                }
+            };
+
+            _cheatTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
+            _cheatTreeView.AppendColumn("Name", new CellRendererText(), "text", 1);
+            _cheatTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);
+
+            var buildIdColumn = _cheatTreeView.AppendColumn("Build Id", new CellRendererText(), "text", 3);
+            buildIdColumn.Visible = false;
+
+            string[] enabled = Array.Empty<string>();
+
+            if (File.Exists(_enabledCheatsPath))
+            {
+                enabled = File.ReadAllLines(_enabledCheatsPath);
+            }
+
+            int cheatAdded = 0;
+
+            var mods = new ModLoader.ModCache();
+
+            ModLoader.QueryContentsDir(mods, new DirectoryInfo(System.IO.Path.Combine(modsBasePath, "contents")), titleId);
+
+            string currentCheatFile = string.Empty;
+            string buildId = string.Empty;
+            TreeIter parentIter = default;
+
+            foreach (var cheat in mods.Cheats)
+            {
+                if (cheat.Path.FullName != currentCheatFile)
+                {
+                    currentCheatFile = cheat.Path.FullName;
+                    string parentPath = currentCheatFile.Replace(titleModsPath, "");
+
+                    buildId = System.IO.Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
+                    parentIter = ((TreeStore)_cheatTreeView.Model).AppendValues(false, buildId, parentPath, "");
+                }
+
+                string cleanName = cheat.Name[1..^7];
+                ((TreeStore)_cheatTreeView.Model).AppendValues(parentIter, enabled.Contains($"{buildId}-{cheat.Name}"), cleanName, "", buildId);
+
+                cheatAdded++;
+            }
+
+            if (cheatAdded == 0)
+            {
+                ((TreeStore)_cheatTreeView.Model).AppendValues(false, "No Cheats Found", "", "");
+                _cheatTreeView.GetColumn(0).Visible = false;
+
+                _noCheatsFound = true;
+
+                _saveButton.Visible = false;
+            }
+
+            _cheatTreeView.ExpandAll();
+        }
+
+        private void SaveButton_Clicked(object sender, EventArgs args)
+        {
+            if (_noCheatsFound)
+            {
+                return;
+            }
+
+            List<string> enabledCheats = new();
+
+            if (_cheatTreeView.Model.GetIterFirst(out TreeIter parentIter))
+            {
+                do
+                {
+                    if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, parentIter))
+                    {
+                        do
+                        {
+                            var enabled = (bool)_cheatTreeView.Model.GetValue(childIter, 0);
+
+                            if (enabled)
+                            {
+                                var name = _cheatTreeView.Model.GetValue(childIter, 1).ToString();
+                                var buildId = _cheatTreeView.Model.GetValue(childIter, 3).ToString();
+
+                                enabledCheats.Add($"{buildId}-<{name} Cheat>");
+                            }
+                        }
+                        while (_cheatTreeView.Model.IterNext(ref childIter));
+                    }
+                }
+                while (_cheatTreeView.Model.IterNext(ref parentIter));
+            }
+
+            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(_enabledCheatsPath));
+
+            File.WriteAllLines(_enabledCheatsPath, enabledCheats);
+
+            Dispose();
+        }
+
+        private void CancelButton_Clicked(object sender, EventArgs args)
+        {
+            Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/CheatWindow.glade b/src/Ryujinx/UI/Windows/CheatWindow.glade
new file mode 100644
index 00000000..9a165f1a
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/CheatWindow.glade
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkWindow" id="_cheatWindow">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - Cheat Manager</property>
+    <property name="default_width">440</property>
+    <property name="default_height">550</property>
+    <child>
+      <object class="GtkBox" id="MainBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkBox" id="CheatBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel" id="_baseTitleInfoLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="label" translatable="yes">Available Cheats</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkTextView" id="_buildIdTextView">
+                <property name="visible">True</property>
+                <property name="margin_top">10</property>
+                <property name="halign">center</property>
+                <property name="margin_bottom">10</property>
+                <property name="editable">False</property>
+                <property name="cursor_visible">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTreeView" id="_cheatTreeView">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <object class="GtkButton" id="_saveButton">
+                    <property name="label" translatable="yes">Save</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_cancelButton">
+                    <property name="label" translatable="yes">Cancel</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Windows/ControllerWindow.cs b/src/Ryujinx/UI/Windows/ControllerWindow.cs
new file mode 100644
index 00000000..95411344
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/ControllerWindow.cs
@@ -0,0 +1,1230 @@
+using Gtk;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Hid.Controller;
+using Ryujinx.Common.Configuration.Hid.Controller.Motion;
+using Ryujinx.Common.Configuration.Hid.Keyboard;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.Input;
+using Ryujinx.Input.Assigner;
+using Ryujinx.Input.GTK3;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text.Json;
+using System.Threading;
+using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
+using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
+using GUI = Gtk.Builder.ObjectAttribute;
+using Key = Ryujinx.Common.Configuration.Hid.Key;
+
+namespace Ryujinx.UI.Windows
+{
+    public class ControllerWindow : Window
+    {
+        private readonly PlayerIndex _playerIndex;
+        private readonly InputConfig _inputConfig;
+
+        private bool _isWaitingForInput;
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] Adjustment _controllerStrongRumble;
+        [GUI] Adjustment _controllerWeakRumble;
+        [GUI] Adjustment _controllerDeadzoneLeft;
+        [GUI] Adjustment _controllerDeadzoneRight;
+        [GUI] Adjustment _controllerRangeLeft;
+        [GUI] Adjustment _controllerRangeRight;
+        [GUI] Adjustment _controllerTriggerThreshold;
+        [GUI] Adjustment _slotNumber;
+        [GUI] Adjustment _altSlotNumber;
+        [GUI] Adjustment _sensitivity;
+        [GUI] Adjustment _gyroDeadzone;
+        [GUI] CheckButton _enableMotion;
+        [GUI] CheckButton _enableCemuHook;
+        [GUI] CheckButton _mirrorInput;
+        [GUI] Entry _dsuServerHost;
+        [GUI] Entry _dsuServerPort;
+        [GUI] ComboBoxText _inputDevice;
+        [GUI] ComboBoxText _profile;
+        [GUI] Box _settingsBox;
+        [GUI] Box _motionAltBox;
+        [GUI] Box _motionBox;
+        [GUI] Box _dsuServerHostBox;
+        [GUI] Box _dsuServerPortBox;
+        [GUI] Box _motionControllerSlot;
+        [GUI] Grid _leftStickKeyboard;
+        [GUI] Grid _leftStickController;
+        [GUI] Box _deadZoneLeftBox;
+        [GUI] Box _rangeLeftBox;
+        [GUI] Grid _rightStickKeyboard;
+        [GUI] Grid _rightStickController;
+        [GUI] Box _deadZoneRightBox;
+        [GUI] Box _rangeRightBox;
+        [GUI] Grid _leftSideTriggerBox;
+        [GUI] Grid _rightSideTriggerBox;
+        [GUI] Box _triggerThresholdBox;
+        [GUI] ComboBoxText _controllerType;
+        [GUI] ToggleButton _lStick;
+        [GUI] CheckButton _invertLStickX;
+        [GUI] CheckButton _invertLStickY;
+        [GUI] CheckButton _rotateL90CW;
+        [GUI] ToggleButton _lStickUp;
+        [GUI] ToggleButton _lStickDown;
+        [GUI] ToggleButton _lStickLeft;
+        [GUI] ToggleButton _lStickRight;
+        [GUI] ToggleButton _lStickButton;
+        [GUI] ToggleButton _dpadUp;
+        [GUI] ToggleButton _dpadDown;
+        [GUI] ToggleButton _dpadLeft;
+        [GUI] ToggleButton _dpadRight;
+        [GUI] ToggleButton _minus;
+        [GUI] ToggleButton _l;
+        [GUI] ToggleButton _zL;
+        [GUI] ToggleButton _rStick;
+        [GUI] CheckButton _invertRStickX;
+        [GUI] CheckButton _invertRStickY;
+        [GUI] CheckButton _rotateR90CW;
+        [GUI] ToggleButton _rStickUp;
+        [GUI] ToggleButton _rStickDown;
+        [GUI] ToggleButton _rStickLeft;
+        [GUI] ToggleButton _rStickRight;
+        [GUI] ToggleButton _rStickButton;
+        [GUI] ToggleButton _a;
+        [GUI] ToggleButton _b;
+        [GUI] ToggleButton _x;
+        [GUI] ToggleButton _y;
+        [GUI] ToggleButton _plus;
+        [GUI] ToggleButton _r;
+        [GUI] ToggleButton _zR;
+        [GUI] ToggleButton _lSl;
+        [GUI] ToggleButton _lSr;
+        [GUI] ToggleButton _rSl;
+        [GUI] ToggleButton _rSr;
+        [GUI] Image _controllerImage;
+        [GUI] CheckButton _enableRumble;
+        [GUI] Box _rumbleBox;
+#pragma warning restore CS0649, IDE0044
+
+        private readonly MainWindow _mainWindow;
+        private readonly IGamepadDriver _gtk3KeyboardDriver;
+        private IGamepad _selectedGamepad;
+        private bool _mousePressed;
+        private bool _middleMousePressed;
+
+        private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+        public ControllerWindow(MainWindow mainWindow, PlayerIndex controllerId) : this(mainWindow, new Builder("Ryujinx.UI.Windows.ControllerWindow.glade"), controllerId) { }
+
+        private ControllerWindow(MainWindow mainWindow, Builder builder, PlayerIndex controllerId) : base(builder.GetRawOwnedObject("_controllerWin"))
+        {
+            _mainWindow = mainWindow;
+            _selectedGamepad = null;
+
+            // NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
+            _gtk3KeyboardDriver = new GTK3KeyboardDriver(this);
+
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            builder.Autoconnect(this);
+
+            _playerIndex = controllerId;
+            _inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerIndex);
+
+            Title = $"Ryujinx - Controller Settings - {_playerIndex}";
+
+            if (_playerIndex == PlayerIndex.Handheld)
+            {
+                _controllerType.Append(ControllerType.Handheld.ToString(), "Handheld");
+                _controllerType.Sensitive = false;
+            }
+            else
+            {
+                _controllerType.Append(ControllerType.ProController.ToString(), "Pro Controller");
+                _controllerType.Append(ControllerType.JoyconPair.ToString(), "Joycon Pair");
+                _controllerType.Append(ControllerType.JoyconLeft.ToString(), "Joycon Left");
+                _controllerType.Append(ControllerType.JoyconRight.ToString(), "Joycon Right");
+            }
+
+            _controllerType.Active = 0; // Set initial value to first in list.
+
+            // Bind Events.
+            _lStick.Clicked += ButtonForStick_Pressed;
+            _lStickUp.Clicked += Button_Pressed;
+            _lStickDown.Clicked += Button_Pressed;
+            _lStickLeft.Clicked += Button_Pressed;
+            _lStickRight.Clicked += Button_Pressed;
+            _lStickButton.Clicked += Button_Pressed;
+            _dpadUp.Clicked += Button_Pressed;
+            _dpadDown.Clicked += Button_Pressed;
+            _dpadLeft.Clicked += Button_Pressed;
+            _dpadRight.Clicked += Button_Pressed;
+            _minus.Clicked += Button_Pressed;
+            _l.Clicked += Button_Pressed;
+            _zL.Clicked += Button_Pressed;
+            _lSl.Clicked += Button_Pressed;
+            _lSr.Clicked += Button_Pressed;
+            _rStick.Clicked += ButtonForStick_Pressed;
+            _rStickUp.Clicked += Button_Pressed;
+            _rStickDown.Clicked += Button_Pressed;
+            _rStickLeft.Clicked += Button_Pressed;
+            _rStickRight.Clicked += Button_Pressed;
+            _rStickButton.Clicked += Button_Pressed;
+            _a.Clicked += Button_Pressed;
+            _b.Clicked += Button_Pressed;
+            _x.Clicked += Button_Pressed;
+            _y.Clicked += Button_Pressed;
+            _plus.Clicked += Button_Pressed;
+            _r.Clicked += Button_Pressed;
+            _zR.Clicked += Button_Pressed;
+            _rSl.Clicked += Button_Pressed;
+            _rSr.Clicked += Button_Pressed;
+            _enableCemuHook.Clicked += CemuHookCheckButtonPressed;
+
+            // Setup current values.
+            UpdateInputDeviceList();
+            SetAvailableOptions();
+
+            ClearValues();
+            if (_inputDevice.ActiveId != null)
+            {
+                SetCurrentValues();
+            }
+
+            mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
+            mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
+
+            _mainWindow.RendererWidget?.NpadManager.BlockInputUpdates();
+        }
+
+        private void CemuHookCheckButtonPressed(object sender, EventArgs e)
+        {
+            UpdateCemuHookSpecificFieldsVisibility();
+        }
+
+        private void HandleOnGamepadDisconnected(string id)
+        {
+            Application.Invoke(delegate
+            {
+                UpdateInputDeviceList();
+            });
+        }
+
+        private void HandleOnGamepadConnected(string id)
+        {
+            Application.Invoke(delegate
+            {
+                UpdateInputDeviceList();
+            });
+        }
+
+        protected override void OnDestroyed()
+        {
+            _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
+            _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
+
+            _mainWindow.RendererWidget?.NpadManager.UnblockInputUpdates();
+
+            _selectedGamepad?.Dispose();
+
+            _gtk3KeyboardDriver.Dispose();
+        }
+
+        private static string GetShortGamepadName(string str)
+        {
+            const string ShrinkChars = "...";
+            const int MaxSize = 50;
+
+            if (str.Length > MaxSize)
+            {
+                return $"{str.AsSpan(0, MaxSize - ShrinkChars.Length)}{ShrinkChars}";
+            }
+
+            return str;
+        }
+
+        private void UpdateInputDeviceList()
+        {
+            _inputDevice.RemoveAll();
+            _inputDevice.Append("disabled", "Disabled");
+            _inputDevice.SetActiveId("disabled");
+
+            foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
+            {
+                IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
+
+                if (gamepad != null)
+                {
+                    _inputDevice.Append($"keyboard/{id}", GetShortGamepadName($"{gamepad.Name} ({id})"));
+
+                    gamepad.Dispose();
+                }
+            }
+
+            foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
+            {
+                IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
+
+                if (gamepad != null)
+                {
+                    _inputDevice.Append($"controller/{id}", GetShortGamepadName($"{gamepad.Name} ({id})"));
+
+                    gamepad.Dispose();
+                }
+            }
+
+            switch (_inputConfig)
+            {
+                case StandardKeyboardInputConfig keyboard:
+                    _inputDevice.SetActiveId($"keyboard/{keyboard.Id}");
+                    break;
+                case StandardControllerInputConfig controller:
+                    _inputDevice.SetActiveId($"controller/{controller.Id}");
+                    break;
+            }
+        }
+
+        private void UpdateCemuHookSpecificFieldsVisibility()
+        {
+            if (_enableCemuHook.Active)
+            {
+                _dsuServerHostBox.Show();
+                _dsuServerPortBox.Show();
+                _motionControllerSlot.Show();
+                _motionAltBox.Show();
+                _mirrorInput.Show();
+            }
+            else
+            {
+                _dsuServerHostBox.Hide();
+                _dsuServerPortBox.Hide();
+                _motionControllerSlot.Hide();
+                _motionAltBox.Hide();
+                _mirrorInput.Hide();
+            }
+        }
+
+        private void SetAvailableOptions()
+        {
+            if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("keyboard"))
+            {
+                ShowAll();
+                _leftStickController.Hide();
+                _rightStickController.Hide();
+                _deadZoneLeftBox.Hide();
+                _deadZoneRightBox.Hide();
+                _rangeLeftBox.Hide();
+                _rangeRightBox.Hide();
+                _triggerThresholdBox.Hide();
+                _motionBox.Hide();
+                _rumbleBox.Hide();
+            }
+            else if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("controller"))
+            {
+                ShowAll();
+                _leftStickKeyboard.Hide();
+                _rightStickKeyboard.Hide();
+
+                UpdateCemuHookSpecificFieldsVisibility();
+            }
+            else
+            {
+                _settingsBox.Hide();
+            }
+
+            ClearValues();
+        }
+
+        private void SetCurrentValues()
+        {
+            SetControllerSpecificFields();
+
+            SetProfiles();
+
+            if (_inputDevice.ActiveId.StartsWith("keyboard") && _inputConfig is StandardKeyboardInputConfig)
+            {
+                SetValues(_inputConfig);
+            }
+            else if (_inputDevice.ActiveId.StartsWith("controller") && _inputConfig is StandardControllerInputConfig)
+            {
+                SetValues(_inputConfig);
+            }
+        }
+
+        private void SetControllerSpecificFields()
+        {
+            _leftSideTriggerBox.Hide();
+            _rightSideTriggerBox.Hide();
+            _motionAltBox.Hide();
+
+            switch (_controllerType.ActiveId)
+            {
+                case "JoyconLeft":
+                    _leftSideTriggerBox.Show();
+                    break;
+                case "JoyconRight":
+                    _rightSideTriggerBox.Show();
+                    break;
+                case "JoyconPair":
+                    _motionAltBox.Show();
+                    break;
+            }
+
+            if (!OperatingSystem.IsMacOS())
+            {
+                _controllerImage.Pixbuf = _controllerType.ActiveId switch
+                {
+                    "ProController" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Controller_ProCon.svg", 400, 400),
+                    "JoyconLeft" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Controller_JoyConLeft.svg", 400, 500),
+                    "JoyconRight" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Controller_JoyConRight.svg", 400, 500),
+                    _ => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Controller_JoyConPair.svg", 400, 500),
+                };
+            }
+        }
+
+        private void ClearValues()
+        {
+            _lStick.Label = "Unbound";
+            _lStickUp.Label = "Unbound";
+            _lStickDown.Label = "Unbound";
+            _lStickLeft.Label = "Unbound";
+            _lStickRight.Label = "Unbound";
+            _lStickButton.Label = "Unbound";
+            _dpadUp.Label = "Unbound";
+            _dpadDown.Label = "Unbound";
+            _dpadLeft.Label = "Unbound";
+            _dpadRight.Label = "Unbound";
+            _minus.Label = "Unbound";
+            _l.Label = "Unbound";
+            _zL.Label = "Unbound";
+            _lSl.Label = "Unbound";
+            _lSr.Label = "Unbound";
+            _rStick.Label = "Unbound";
+            _rStickUp.Label = "Unbound";
+            _rStickDown.Label = "Unbound";
+            _rStickLeft.Label = "Unbound";
+            _rStickRight.Label = "Unbound";
+            _rStickButton.Label = "Unbound";
+            _a.Label = "Unbound";
+            _b.Label = "Unbound";
+            _x.Label = "Unbound";
+            _y.Label = "Unbound";
+            _plus.Label = "Unbound";
+            _r.Label = "Unbound";
+            _zR.Label = "Unbound";
+            _rSl.Label = "Unbound";
+            _rSr.Label = "Unbound";
+            _controllerStrongRumble.Value = 1;
+            _controllerWeakRumble.Value = 1;
+            _controllerDeadzoneLeft.Value = 0;
+            _controllerDeadzoneRight.Value = 0;
+            _controllerRangeLeft.Value = 1;
+            _controllerRangeRight.Value = 1;
+            _controllerTriggerThreshold.Value = 0;
+            _mirrorInput.Active = false;
+            _enableMotion.Active = false;
+            _enableCemuHook.Active = false;
+            _slotNumber.Value = 0;
+            _altSlotNumber.Value = 0;
+            _sensitivity.Value = 100;
+            _gyroDeadzone.Value = 1;
+            _dsuServerHost.Buffer.Text = "";
+            _dsuServerPort.Buffer.Text = "";
+            _enableRumble.Active = false;
+        }
+
+        private void SetValues(InputConfig config)
+        {
+            switch (config)
+            {
+                case StandardKeyboardInputConfig keyboardConfig:
+                    if (!_controllerType.SetActiveId(keyboardConfig.ControllerType.ToString()))
+                    {
+                        _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
+                            ? ControllerType.Handheld.ToString()
+                            : ControllerType.ProController.ToString());
+                    }
+
+                    _lStickUp.Label = keyboardConfig.LeftJoyconStick.StickUp.ToString();
+                    _lStickDown.Label = keyboardConfig.LeftJoyconStick.StickDown.ToString();
+                    _lStickLeft.Label = keyboardConfig.LeftJoyconStick.StickLeft.ToString();
+                    _lStickRight.Label = keyboardConfig.LeftJoyconStick.StickRight.ToString();
+                    _lStickButton.Label = keyboardConfig.LeftJoyconStick.StickButton.ToString();
+                    _dpadUp.Label = keyboardConfig.LeftJoycon.DpadUp.ToString();
+                    _dpadDown.Label = keyboardConfig.LeftJoycon.DpadDown.ToString();
+                    _dpadLeft.Label = keyboardConfig.LeftJoycon.DpadLeft.ToString();
+                    _dpadRight.Label = keyboardConfig.LeftJoycon.DpadRight.ToString();
+                    _minus.Label = keyboardConfig.LeftJoycon.ButtonMinus.ToString();
+                    _l.Label = keyboardConfig.LeftJoycon.ButtonL.ToString();
+                    _zL.Label = keyboardConfig.LeftJoycon.ButtonZl.ToString();
+                    _lSl.Label = keyboardConfig.LeftJoycon.ButtonSl.ToString();
+                    _lSr.Label = keyboardConfig.LeftJoycon.ButtonSr.ToString();
+                    _rStickUp.Label = keyboardConfig.RightJoyconStick.StickUp.ToString();
+                    _rStickDown.Label = keyboardConfig.RightJoyconStick.StickDown.ToString();
+                    _rStickLeft.Label = keyboardConfig.RightJoyconStick.StickLeft.ToString();
+                    _rStickRight.Label = keyboardConfig.RightJoyconStick.StickRight.ToString();
+                    _rStickButton.Label = keyboardConfig.RightJoyconStick.StickButton.ToString();
+                    _a.Label = keyboardConfig.RightJoycon.ButtonA.ToString();
+                    _b.Label = keyboardConfig.RightJoycon.ButtonB.ToString();
+                    _x.Label = keyboardConfig.RightJoycon.ButtonX.ToString();
+                    _y.Label = keyboardConfig.RightJoycon.ButtonY.ToString();
+                    _plus.Label = keyboardConfig.RightJoycon.ButtonPlus.ToString();
+                    _r.Label = keyboardConfig.RightJoycon.ButtonR.ToString();
+                    _zR.Label = keyboardConfig.RightJoycon.ButtonZr.ToString();
+                    _rSl.Label = keyboardConfig.RightJoycon.ButtonSl.ToString();
+                    _rSr.Label = keyboardConfig.RightJoycon.ButtonSr.ToString();
+                    break;
+
+                case StandardControllerInputConfig controllerConfig:
+                    if (!_controllerType.SetActiveId(controllerConfig.ControllerType.ToString()))
+                    {
+                        _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
+                            ? ControllerType.Handheld.ToString()
+                            : ControllerType.ProController.ToString());
+                    }
+
+                    _lStick.Label = controllerConfig.LeftJoyconStick.Joystick.ToString();
+                    _invertLStickX.Active = controllerConfig.LeftJoyconStick.InvertStickX;
+                    _invertLStickY.Active = controllerConfig.LeftJoyconStick.InvertStickY;
+                    _rotateL90CW.Active = controllerConfig.LeftJoyconStick.Rotate90CW;
+                    _lStickButton.Label = controllerConfig.LeftJoyconStick.StickButton.ToString();
+                    _dpadUp.Label = controllerConfig.LeftJoycon.DpadUp.ToString();
+                    _dpadDown.Label = controllerConfig.LeftJoycon.DpadDown.ToString();
+                    _dpadLeft.Label = controllerConfig.LeftJoycon.DpadLeft.ToString();
+                    _dpadRight.Label = controllerConfig.LeftJoycon.DpadRight.ToString();
+                    _minus.Label = controllerConfig.LeftJoycon.ButtonMinus.ToString();
+                    _l.Label = controllerConfig.LeftJoycon.ButtonL.ToString();
+                    _zL.Label = controllerConfig.LeftJoycon.ButtonZl.ToString();
+                    _lSl.Label = controllerConfig.LeftJoycon.ButtonSl.ToString();
+                    _lSr.Label = controllerConfig.LeftJoycon.ButtonSr.ToString();
+                    _rStick.Label = controllerConfig.RightJoyconStick.Joystick.ToString();
+                    _invertRStickX.Active = controllerConfig.RightJoyconStick.InvertStickX;
+                    _invertRStickY.Active = controllerConfig.RightJoyconStick.InvertStickY;
+                    _rotateR90CW.Active = controllerConfig.RightJoyconStick.Rotate90CW;
+                    _rStickButton.Label = controllerConfig.RightJoyconStick.StickButton.ToString();
+                    _a.Label = controllerConfig.RightJoycon.ButtonA.ToString();
+                    _b.Label = controllerConfig.RightJoycon.ButtonB.ToString();
+                    _x.Label = controllerConfig.RightJoycon.ButtonX.ToString();
+                    _y.Label = controllerConfig.RightJoycon.ButtonY.ToString();
+                    _plus.Label = controllerConfig.RightJoycon.ButtonPlus.ToString();
+                    _r.Label = controllerConfig.RightJoycon.ButtonR.ToString();
+                    _zR.Label = controllerConfig.RightJoycon.ButtonZr.ToString();
+                    _rSl.Label = controllerConfig.RightJoycon.ButtonSl.ToString();
+                    _rSr.Label = controllerConfig.RightJoycon.ButtonSr.ToString();
+                    _controllerStrongRumble.Value = controllerConfig.Rumble.StrongRumble;
+                    _controllerWeakRumble.Value = controllerConfig.Rumble.WeakRumble;
+                    _enableRumble.Active = controllerConfig.Rumble.EnableRumble;
+                    _controllerDeadzoneLeft.Value = controllerConfig.DeadzoneLeft;
+                    _controllerDeadzoneRight.Value = controllerConfig.DeadzoneRight;
+                    _controllerRangeLeft.Value = controllerConfig.RangeLeft;
+                    _controllerRangeRight.Value = controllerConfig.RangeRight;
+                    _controllerTriggerThreshold.Value = controllerConfig.TriggerThreshold;
+                    _sensitivity.Value = controllerConfig.Motion.Sensitivity;
+                    _gyroDeadzone.Value = controllerConfig.Motion.GyroDeadzone;
+                    _enableMotion.Active = controllerConfig.Motion.EnableMotion;
+                    _enableCemuHook.Active = controllerConfig.Motion.MotionBackend == MotionInputBackendType.CemuHook;
+
+                    // If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
+                    if (_controllerRangeLeft.Value <= 0.0 && _controllerRangeRight.Value <= 0.0)
+                    {
+                        _controllerRangeLeft.Value = 1.0;
+                        _controllerRangeRight.Value = 1.0;
+
+                        Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
+                    }
+
+                    if (controllerConfig.Motion is CemuHookMotionConfigController cemuHookMotionConfig)
+                    {
+                        _slotNumber.Value = cemuHookMotionConfig.Slot;
+                        _altSlotNumber.Value = cemuHookMotionConfig.AltSlot;
+                        _mirrorInput.Active = cemuHookMotionConfig.MirrorInput;
+                        _dsuServerHost.Buffer.Text = cemuHookMotionConfig.DsuServerHost;
+                        _dsuServerPort.Buffer.Text = cemuHookMotionConfig.DsuServerPort.ToString();
+                    }
+
+                    break;
+            }
+        }
+
+        private InputConfig GetValues()
+        {
+            if (_inputDevice.ActiveId.StartsWith("keyboard"))
+            {
+#pragma warning disable CA1806, IDE0055 // Disable formatting
+                Enum.TryParse(_lStickUp.Label,     out Key lStickUp);
+                Enum.TryParse(_lStickDown.Label,   out Key lStickDown);
+                Enum.TryParse(_lStickLeft.Label,   out Key lStickLeft);
+                Enum.TryParse(_lStickRight.Label,  out Key lStickRight);
+                Enum.TryParse(_lStickButton.Label, out Key lStickButton);
+                Enum.TryParse(_dpadUp.Label,       out Key lDPadUp);
+                Enum.TryParse(_dpadDown.Label,     out Key lDPadDown);
+                Enum.TryParse(_dpadLeft.Label,     out Key lDPadLeft);
+                Enum.TryParse(_dpadRight.Label,    out Key lDPadRight);
+                Enum.TryParse(_minus.Label,        out Key lButtonMinus);
+                Enum.TryParse(_l.Label,            out Key lButtonL);
+                Enum.TryParse(_zL.Label,           out Key lButtonZl);
+                Enum.TryParse(_lSl.Label,          out Key lButtonSl);
+                Enum.TryParse(_lSr.Label,          out Key lButtonSr);
+
+                Enum.TryParse(_rStickUp.Label,     out Key rStickUp);
+                Enum.TryParse(_rStickDown.Label,   out Key rStickDown);
+                Enum.TryParse(_rStickLeft.Label,   out Key rStickLeft);
+                Enum.TryParse(_rStickRight.Label,  out Key rStickRight);
+                Enum.TryParse(_rStickButton.Label, out Key rStickButton);
+                Enum.TryParse(_a.Label,            out Key rButtonA);
+                Enum.TryParse(_b.Label,            out Key rButtonB);
+                Enum.TryParse(_x.Label,            out Key rButtonX);
+                Enum.TryParse(_y.Label,            out Key rButtonY);
+                Enum.TryParse(_plus.Label,         out Key rButtonPlus);
+                Enum.TryParse(_r.Label,            out Key rButtonR);
+                Enum.TryParse(_zR.Label,           out Key rButtonZr);
+                Enum.TryParse(_rSl.Label,          out Key rButtonSl);
+                Enum.TryParse(_rSr.Label,          out Key rButtonSr);
+#pragma warning restore CA1806, IDE0055
+
+                return new StandardKeyboardInputConfig
+                {
+                    Backend = InputBackendType.WindowKeyboard,
+                    Version = InputConfig.CurrentVersion,
+                    Id = _inputDevice.ActiveId.Split("/")[1],
+                    ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId),
+                    PlayerIndex = _playerIndex,
+                    LeftJoycon = new LeftJoyconCommonConfig<Key>
+                    {
+                        ButtonMinus = lButtonMinus,
+                        ButtonL = lButtonL,
+                        ButtonZl = lButtonZl,
+                        ButtonSl = lButtonSl,
+                        ButtonSr = lButtonSr,
+                        DpadUp = lDPadUp,
+                        DpadDown = lDPadDown,
+                        DpadLeft = lDPadLeft,
+                        DpadRight = lDPadRight,
+                    },
+                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = lStickUp,
+                        StickDown = lStickDown,
+                        StickLeft = lStickLeft,
+                        StickRight = lStickRight,
+                        StickButton = lStickButton,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<Key>
+                    {
+                        ButtonA = rButtonA,
+                        ButtonB = rButtonB,
+                        ButtonX = rButtonX,
+                        ButtonY = rButtonY,
+                        ButtonPlus = rButtonPlus,
+                        ButtonR = rButtonR,
+                        ButtonZr = rButtonZr,
+                        ButtonSl = rButtonSl,
+                        ButtonSr = rButtonSr,
+                    },
+                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = rStickUp,
+                        StickDown = rStickDown,
+                        StickLeft = rStickLeft,
+                        StickRight = rStickRight,
+                        StickButton = rStickButton,
+                    },
+                };
+            }
+
+            if (_inputDevice.ActiveId.StartsWith("controller"))
+            {
+#pragma warning disable CA1806, IDE0055 // Disable formatting
+                Enum.TryParse(_lStick.Label,       out ConfigStickInputId   lStick);
+                Enum.TryParse(_lStickButton.Label, out ConfigGamepadInputId lStickButton);
+                Enum.TryParse(_minus.Label,        out ConfigGamepadInputId lButtonMinus);
+                Enum.TryParse(_l.Label,            out ConfigGamepadInputId lButtonL);
+                Enum.TryParse(_zL.Label,           out ConfigGamepadInputId lButtonZl);
+                Enum.TryParse(_lSl.Label,          out ConfigGamepadInputId lButtonSl);
+                Enum.TryParse(_lSr.Label,          out ConfigGamepadInputId lButtonSr);
+                Enum.TryParse(_dpadUp.Label,       out ConfigGamepadInputId lDPadUp);
+                Enum.TryParse(_dpadDown.Label,     out ConfigGamepadInputId lDPadDown);
+                Enum.TryParse(_dpadLeft.Label,     out ConfigGamepadInputId lDPadLeft);
+                Enum.TryParse(_dpadRight.Label,    out ConfigGamepadInputId lDPadRight);
+
+                Enum.TryParse(_rStick.Label,       out ConfigStickInputId   rStick);
+                Enum.TryParse(_rStickButton.Label, out ConfigGamepadInputId rStickButton);
+                Enum.TryParse(_a.Label,            out ConfigGamepadInputId rButtonA);
+                Enum.TryParse(_b.Label,            out ConfigGamepadInputId rButtonB);
+                Enum.TryParse(_x.Label,            out ConfigGamepadInputId rButtonX);
+                Enum.TryParse(_y.Label,            out ConfigGamepadInputId rButtonY);
+                Enum.TryParse(_plus.Label,         out ConfigGamepadInputId rButtonPlus);
+                Enum.TryParse(_r.Label,            out ConfigGamepadInputId rButtonR);
+                Enum.TryParse(_zR.Label,           out ConfigGamepadInputId rButtonZr);
+                Enum.TryParse(_rSl.Label,          out ConfigGamepadInputId rButtonSl);
+                Enum.TryParse(_rSr.Label,          out ConfigGamepadInputId rButtonSr);
+
+                int.TryParse(_dsuServerPort.Buffer.Text, out int port);
+#pragma warning restore CA1806, IDE0055
+
+                MotionConfigController motionConfig;
+
+                if (_enableCemuHook.Active)
+                {
+                    motionConfig = new CemuHookMotionConfigController
+                    {
+                        MotionBackend = MotionInputBackendType.CemuHook,
+                        EnableMotion = _enableMotion.Active,
+                        Sensitivity = (int)_sensitivity.Value,
+                        GyroDeadzone = _gyroDeadzone.Value,
+                        MirrorInput = _mirrorInput.Active,
+                        Slot = (int)_slotNumber.Value,
+                        AltSlot = (int)_altSlotNumber.Value,
+                        DsuServerHost = _dsuServerHost.Buffer.Text,
+                        DsuServerPort = port,
+                    };
+                }
+                else
+                {
+                    motionConfig = new StandardMotionConfigController
+                    {
+                        MotionBackend = MotionInputBackendType.GamepadDriver,
+                        EnableMotion = _enableMotion.Active,
+                        Sensitivity = (int)_sensitivity.Value,
+                        GyroDeadzone = _gyroDeadzone.Value,
+                    };
+                }
+
+                return new StandardControllerInputConfig
+                {
+                    Backend = InputBackendType.GamepadSDL2,
+                    Version = InputConfig.CurrentVersion,
+                    Id = _inputDevice.ActiveId.Split("/")[1].Split(" ")[0],
+                    ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId),
+                    PlayerIndex = _playerIndex,
+                    DeadzoneLeft = (float)_controllerDeadzoneLeft.Value,
+                    DeadzoneRight = (float)_controllerDeadzoneRight.Value,
+                    RangeLeft = (float)_controllerRangeLeft.Value,
+                    RangeRight = (float)_controllerRangeRight.Value,
+                    TriggerThreshold = (float)_controllerTriggerThreshold.Value,
+                    LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
+                    {
+                        ButtonMinus = lButtonMinus,
+                        ButtonL = lButtonL,
+                        ButtonZl = lButtonZl,
+                        ButtonSl = lButtonSl,
+                        ButtonSr = lButtonSr,
+                        DpadUp = lDPadUp,
+                        DpadDown = lDPadDown,
+                        DpadLeft = lDPadLeft,
+                        DpadRight = lDPadRight,
+                    },
+                    LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                    {
+                        InvertStickX = _invertLStickX.Active,
+                        Joystick = lStick,
+                        InvertStickY = _invertLStickY.Active,
+                        StickButton = lStickButton,
+                        Rotate90CW = _rotateL90CW.Active,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
+                    {
+                        ButtonA = rButtonA,
+                        ButtonB = rButtonB,
+                        ButtonX = rButtonX,
+                        ButtonY = rButtonY,
+                        ButtonPlus = rButtonPlus,
+                        ButtonR = rButtonR,
+                        ButtonZr = rButtonZr,
+                        ButtonSl = rButtonSl,
+                        ButtonSr = rButtonSr,
+                    },
+                    RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                    {
+                        InvertStickX = _invertRStickX.Active,
+                        Joystick = rStick,
+                        InvertStickY = _invertRStickY.Active,
+                        StickButton = rStickButton,
+                        Rotate90CW = _rotateR90CW.Active,
+                    },
+                    Motion = motionConfig,
+                    Rumble = new RumbleConfigController
+                    {
+                        StrongRumble = (float)_controllerStrongRumble.Value,
+                        WeakRumble = (float)_controllerWeakRumble.Value,
+                        EnableRumble = _enableRumble.Active,
+                    },
+                };
+            }
+
+            if (!_inputDevice.ActiveId.StartsWith("disabled"))
+            {
+                GtkDialog.CreateErrorDialog("Invalid data detected in one or more fields; the configuration was not saved.");
+            }
+
+            return null;
+        }
+
+        private string GetProfileBasePath()
+        {
+            if (_inputDevice.ActiveId.StartsWith("keyboard"))
+            {
+                return System.IO.Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
+            }
+            else if (_inputDevice.ActiveId.StartsWith("controller"))
+            {
+                return System.IO.Path.Combine(AppDataManager.ProfilesDirPath, "controller");
+            }
+
+            return AppDataManager.ProfilesDirPath;
+        }
+
+        //
+        // Events
+        //
+        private void InputDevice_Changed(object sender, EventArgs args)
+        {
+            SetAvailableOptions();
+            SetControllerSpecificFields();
+
+            _selectedGamepad?.Dispose();
+            _selectedGamepad = null;
+
+            if (_inputDevice.ActiveId != null)
+            {
+                SetProfiles();
+
+                string id = GetCurrentGamepadId();
+
+                if (_inputDevice.ActiveId.StartsWith("keyboard"))
+                {
+                    if (_inputConfig is StandardKeyboardInputConfig)
+                    {
+                        SetValues(_inputConfig);
+                    }
+
+                    if (_mainWindow.InputManager.KeyboardDriver is GTK3KeyboardDriver)
+                    {
+                        // NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
+                        _selectedGamepad = _gtk3KeyboardDriver.GetGamepad(id);
+                    }
+                    else
+                    {
+                        _selectedGamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
+                    }
+                }
+                else if (_inputDevice.ActiveId.StartsWith("controller"))
+                {
+                    if (_inputConfig is StandardControllerInputConfig)
+                    {
+                        SetValues(_inputConfig);
+                    }
+
+                    _selectedGamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
+                }
+            }
+        }
+
+        private string GetCurrentGamepadId()
+        {
+            if (_inputDevice.ActiveId == null || _inputDevice.ActiveId == "disabled")
+            {
+                return null;
+            }
+
+            return _inputDevice.ActiveId.Split("/")[1].Split(" ")[0];
+        }
+
+        private void Controller_Changed(object sender, EventArgs args)
+        {
+            SetControllerSpecificFields();
+        }
+
+        private IButtonAssigner CreateButtonAssigner(bool forStick)
+        {
+            IButtonAssigner assigner;
+
+            if (_inputDevice.ActiveId.StartsWith("keyboard"))
+            {
+                assigner = new KeyboardKeyAssigner((IKeyboard)_selectedGamepad);
+            }
+            else if (_inputDevice.ActiveId.StartsWith("controller"))
+            {
+                assigner = new GamepadButtonAssigner(_selectedGamepad, (float)_controllerTriggerThreshold.Value, forStick);
+            }
+            else
+            {
+                throw new Exception("Controller not supported");
+            }
+
+            return assigner;
+        }
+
+        private void HandleButtonPressed(ToggleButton button, bool forStick)
+        {
+            if (_isWaitingForInput)
+            {
+                button.Active = false;
+
+                return;
+            }
+
+            _mousePressed = false;
+
+            ButtonPressEvent += MouseClick;
+
+            IButtonAssigner assigner = CreateButtonAssigner(forStick);
+
+            _isWaitingForInput = true;
+
+            // Open GTK3 keyboard for cancel operations
+            IKeyboard keyboard = (IKeyboard)_gtk3KeyboardDriver.GetGamepad("0");
+
+            Thread inputThread = new(() =>
+            {
+                assigner.Initialize();
+
+                while (true)
+                {
+                    Thread.Sleep(10);
+                    assigner.ReadInput();
+
+                    if (_mousePressed || keyboard.IsPressed(Ryujinx.Input.Key.Escape) || assigner.HasAnyButtonPressed() || assigner.ShouldCancel())
+                    {
+                        break;
+                    }
+                }
+
+                string pressedButton = assigner.GetPressedButton();
+
+                Application.Invoke(delegate
+                {
+                    if (_middleMousePressed)
+                    {
+                        button.Label = "Unbound";
+                    }
+                    else if (pressedButton != "")
+                    {
+                        button.Label = pressedButton;
+                    }
+
+                    _middleMousePressed = false;
+
+                    ButtonPressEvent -= MouseClick;
+                    keyboard.Dispose();
+
+                    button.Active = false;
+                    _isWaitingForInput = false;
+                });
+            })
+            {
+                Name = "GUI.InputThread",
+                IsBackground = true,
+            };
+            inputThread.Start();
+        }
+
+        private void Button_Pressed(object sender, EventArgs args)
+        {
+            HandleButtonPressed((ToggleButton)sender, false);
+        }
+
+        private void ButtonForStick_Pressed(object sender, EventArgs args)
+        {
+            HandleButtonPressed((ToggleButton)sender, true);
+        }
+
+        private void MouseClick(object sender, ButtonPressEventArgs args)
+        {
+            _mousePressed = true;
+            _middleMousePressed = args.Event.Button == 2;
+        }
+
+        private void SetProfiles()
+        {
+            _profile.RemoveAll();
+
+            string basePath = GetProfileBasePath();
+
+            if (!Directory.Exists(basePath))
+            {
+                Directory.CreateDirectory(basePath);
+            }
+
+            if (_inputDevice.ActiveId == null || _inputDevice.ActiveId.Equals("disabled"))
+            {
+                _profile.Append("default", "None");
+            }
+            else
+            {
+                _profile.Append("default", "Default");
+
+                foreach (string profile in Directory.GetFiles(basePath, "*.*", SearchOption.AllDirectories))
+                {
+                    _profile.Append(System.IO.Path.GetFileName(profile), System.IO.Path.GetFileNameWithoutExtension(profile));
+                }
+            }
+
+            _profile.SetActiveId("default");
+        }
+
+        private void ProfileLoad_Activated(object sender, EventArgs args)
+        {
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+
+            if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == null)
+            {
+                return;
+            }
+
+            InputConfig config = null;
+            int pos = _profile.Active;
+
+            if (_profile.ActiveId == "default")
+            {
+                if (_inputDevice.ActiveId.StartsWith("keyboard"))
+                {
+                    config = new StandardKeyboardInputConfig
+                    {
+                        Version = InputConfig.CurrentVersion,
+                        Backend = InputBackendType.WindowKeyboard,
+                        Id = null,
+                        ControllerType = ControllerType.ProController,
+                        LeftJoycon = new LeftJoyconCommonConfig<Key>
+                        {
+                            DpadUp = Key.Up,
+                            DpadDown = Key.Down,
+                            DpadLeft = Key.Left,
+                            DpadRight = Key.Right,
+                            ButtonMinus = Key.Minus,
+                            ButtonL = Key.E,
+                            ButtonZl = Key.Q,
+                            ButtonSl = Key.Unbound,
+                            ButtonSr = Key.Unbound,
+                        },
+
+                        LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
+                        {
+                            StickUp = Key.W,
+                            StickDown = Key.S,
+                            StickLeft = Key.A,
+                            StickRight = Key.D,
+                            StickButton = Key.F,
+                        },
+
+                        RightJoycon = new RightJoyconCommonConfig<Key>
+                        {
+                            ButtonA = Key.Z,
+                            ButtonB = Key.X,
+                            ButtonX = Key.C,
+                            ButtonY = Key.V,
+                            ButtonPlus = Key.Plus,
+                            ButtonR = Key.U,
+                            ButtonZr = Key.O,
+                            ButtonSl = Key.Unbound,
+                            ButtonSr = Key.Unbound,
+                        },
+
+                        RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                        {
+                            StickUp = Key.I,
+                            StickDown = Key.K,
+                            StickLeft = Key.J,
+                            StickRight = Key.L,
+                            StickButton = Key.H,
+                        },
+                    };
+                }
+                else if (_inputDevice.ActiveId.StartsWith("controller"))
+                {
+                    bool isNintendoStyle = _inputDevice.ActiveText.Contains("Nintendo");
+
+                    config = new StandardControllerInputConfig
+                    {
+                        Version = InputConfig.CurrentVersion,
+                        Backend = InputBackendType.GamepadSDL2,
+                        Id = null,
+                        ControllerType = ControllerType.JoyconPair,
+                        DeadzoneLeft = 0.1f,
+                        DeadzoneRight = 0.1f,
+                        RangeLeft = 1.0f,
+                        RangeRight = 1.0f,
+                        TriggerThreshold = 0.5f,
+                        LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
+                        {
+                            DpadUp = ConfigGamepadInputId.DpadUp,
+                            DpadDown = ConfigGamepadInputId.DpadDown,
+                            DpadLeft = ConfigGamepadInputId.DpadLeft,
+                            DpadRight = ConfigGamepadInputId.DpadRight,
+                            ButtonMinus = ConfigGamepadInputId.Minus,
+                            ButtonL = ConfigGamepadInputId.LeftShoulder,
+                            ButtonZl = ConfigGamepadInputId.LeftTrigger,
+                            ButtonSl = ConfigGamepadInputId.Unbound,
+                            ButtonSr = ConfigGamepadInputId.Unbound,
+                        },
+
+                        LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                        {
+                            Joystick = ConfigStickInputId.Left,
+                            StickButton = ConfigGamepadInputId.LeftStick,
+                            InvertStickX = false,
+                            InvertStickY = false,
+                            Rotate90CW = false,
+                        },
+
+                        RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
+                        {
+                            ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
+                            ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
+                            ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
+                            ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
+                            ButtonPlus = ConfigGamepadInputId.Plus,
+                            ButtonR = ConfigGamepadInputId.RightShoulder,
+                            ButtonZr = ConfigGamepadInputId.RightTrigger,
+                            ButtonSl = ConfigGamepadInputId.Unbound,
+                            ButtonSr = ConfigGamepadInputId.Unbound,
+                        },
+
+                        RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                        {
+                            Joystick = ConfigStickInputId.Right,
+                            StickButton = ConfigGamepadInputId.RightStick,
+                            InvertStickX = false,
+                            InvertStickY = false,
+                            Rotate90CW = false,
+                        },
+
+                        Motion = new StandardMotionConfigController
+                        {
+                            MotionBackend = MotionInputBackendType.GamepadDriver,
+                            EnableMotion = true,
+                            Sensitivity = 100,
+                            GyroDeadzone = 1,
+                        },
+                        Rumble = new RumbleConfigController
+                        {
+                            StrongRumble = 1f,
+                            WeakRumble = 1f,
+                            EnableRumble = false,
+                        },
+                    };
+                }
+            }
+            else
+            {
+                string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId);
+
+                if (!File.Exists(path))
+                {
+                    if (pos >= 0)
+                    {
+                        _profile.Remove(pos);
+                    }
+
+                    return;
+                }
+
+                try
+                {
+                    config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
+                }
+                catch (JsonException) { }
+            }
+
+            SetValues(config);
+        }
+
+        private void ProfileAdd_Activated(object sender, EventArgs args)
+        {
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+
+            if (_inputDevice.ActiveId == "disabled")
+            {
+                return;
+            }
+
+            InputConfig inputConfig = GetValues();
+            ProfileDialog profileDialog = new();
+
+            if (inputConfig == null)
+            {
+                return;
+            }
+
+            if (profileDialog.Run() == (int)ResponseType.Ok)
+            {
+                string path = System.IO.Path.Combine(GetProfileBasePath(), profileDialog.FileName);
+                string jsonString = JsonHelper.Serialize(inputConfig, _serializerContext.InputConfig);
+
+                File.WriteAllText(path, jsonString);
+            }
+
+            profileDialog.Dispose();
+
+            SetProfiles();
+        }
+
+        private void ProfileRemove_Activated(object sender, EventArgs args)
+        {
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+
+            if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == "default" || _profile.ActiveId == null)
+            {
+                return;
+            }
+
+            MessageDialog confirmDialog = GtkDialog.CreateConfirmationDialog("Deleting Profile", "This action is irreversible, are you sure you want to continue?");
+
+            if (confirmDialog.Run() == (int)ResponseType.Yes)
+            {
+                string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId);
+
+                if (File.Exists(path))
+                {
+                    File.Delete(path);
+                }
+
+                SetProfiles();
+            }
+        }
+
+        private void SaveToggle_Activated(object sender, EventArgs args)
+        {
+            InputConfig inputConfig = GetValues();
+
+            var newConfig = new List<InputConfig>();
+            newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
+
+            if (_inputConfig == null && inputConfig != null)
+            {
+                newConfig.Add(inputConfig);
+            }
+            else
+            {
+                if (_inputDevice.ActiveId == "disabled")
+                {
+                    newConfig.Remove(_inputConfig);
+                }
+                else if (inputConfig != null)
+                {
+                    int index = newConfig.IndexOf(_inputConfig);
+
+                    newConfig[index] = inputConfig;
+                }
+            }
+
+            _mainWindow.RendererWidget?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
+
+            // Atomically replace and signal input change.
+            // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
+            ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
+
+            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+
+            Dispose();
+        }
+
+        private void CloseToggle_Activated(object sender, EventArgs args)
+        {
+            Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/ControllerWindow.glade b/src/Ryujinx/UI/Windows/ControllerWindow.glade
new file mode 100644
index 00000000..e433f5cc
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/ControllerWindow.glade
@@ -0,0 +1,2241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkAdjustment" id="_altSlotNumber">
+    <property name="upper">4</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">4</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerStrongRumble">
+    <property name="lower">0.1</property>
+    <property name="upper">10</property>
+    <property name="value">1.0</property>
+    <property name="step_increment">0.1</property>
+    <property name="page_increment">1.0</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerWeakRumble">
+    <property name="lower">0.1</property>
+    <property name="upper">10</property>
+    <property name="value">1.0</property>
+    <property name="step_increment">0.1</property>
+    <property name="page_increment">1.0</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerDeadzoneLeft">
+    <property name="upper">1</property>
+    <property name="value">0.050000000000000003</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerDeadzoneRight">
+    <property name="upper">1</property>
+    <property name="value">0.050000000000000003</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerRangeLeft">
+    <property name="upper">2</property>
+    <property name="value">1.000000000000000003</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerRangeRight">
+    <property name="upper">2</property>
+    <property name="value">1.000000000000000003</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_controllerTriggerThreshold">
+    <property name="upper">1</property>
+    <property name="value">0.5</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_gyroDeadzone">
+    <property name="upper">100</property>
+    <property name="value">0.01</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+    <property name="page_size">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="_sensitivity">
+    <property name="upper">1000</property>
+    <property name="value">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">4</property>
+  </object>
+  <object class="GtkAdjustment" id="_slotNumber">
+    <property name="upper">4</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">4</property>
+  </object>
+  <object class="GtkWindow" id="_controllerWin">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - Controller Settings</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="default_width">1200</property>
+    <property name="default_height">720</property>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkBox" id="HeadBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">10</property>
+                        <property name="margin_top">10</property>
+                        <property name="margin_bottom">10</property>
+                        <child>
+                          <object class="GtkBox" id="DeviceBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_right">5</property>
+                                <property name="label" translatable="yes">Input Device</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBoxText" id="_inputDevice">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="active">0</property>
+                                <property name="active_id">disabled</property>
+                                <items>
+                                  <item id="disabled" translatable="yes">Disabled</item>
+                                </items>
+                                <signal name="changed" handler="InputDevice_Changed" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="ControllerTypeBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_left">20</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="tooltip_text" translatable="yes">The controller's type</property>
+                                <property name="halign">center</property>
+                                <property name="margin_right">5</property>
+                                <property name="label" translatable="yes">Controller Type:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBoxText" id="_controllerType">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="tooltip_text" translatable="yes">The controller's type</property>
+                                <property name="active">0</property>
+                                <signal name="changed" handler="Controller_Changed" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="ProfileBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_left">20</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_right">5</property>
+                                <property name="label" translatable="yes">Profile:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBoxText" id="_profile">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_right">5</property>
+                                <property name="active">0</property>
+                                <property name="active_id">default</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkToggleButton">
+                                <property name="label" translatable="yes">Load</property>
+                                <property name="width_request">60</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="margin_right">5</property>
+                                <signal name="toggled" handler="ProfileLoad_Activated" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkToggleButton">
+                                <property name="label" translatable="yes">Add</property>
+                                <property name="width_request">60</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="margin_right">5</property>
+                                <signal name="toggled" handler="ProfileAdd_Activated" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkToggleButton">
+                                <property name="label" translatable="yes">Remove</property>
+                                <property name="width_request">60</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <signal name="toggled" handler="ProfileRemove_Activated" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">4</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="_settingsBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_left">10</property>
+                                <property name="margin_top">5</property>
+                                <child>
+                                  <object class="GtkBox" id="ButtonsBox">
+                                    <property name="width_request">156</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Buttons</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">A</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">B</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">X</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Y</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_a">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_b">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_x">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_y">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">+</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">4</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">-</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">5</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_minus">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">5</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_plus">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">4</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSeparator">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="LeftStickBox">
+                                    <property name="width_request">160</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_left">10</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Left Stick</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick Button</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStickButton">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_leftStickKeyboard">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStickDown">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStickUp">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStickLeft">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStickRight">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick Down</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick Up</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick Right</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick Left</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_leftStickController">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">LStick</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lStick">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_invertLStickX">
+                                            <property name="label" translatable="yes">Invert Stick X</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_invertLStickY">
+                                            <property name="label" translatable="yes">Invert Stick Y</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_rotateL90CW">
+                                            <property name="label" translatable="yes">Rotate 90° Clockwise</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_deadZoneLeftBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="halign">start</property>
+                                            <property name="label" translatable="yes">Deadzone Left</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScale">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="adjustment">_controllerDeadzoneLeft</property>
+                                            <property name="round_digits">2</property>
+                                            <property name="digits">2</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">True</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_rangeLeftBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="halign">start</property>
+                                            <property name="label" translatable="yes">Range Left</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScale">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="adjustment">_controllerRangeLeft</property>
+                                            <property name="round_digits">2</property>
+                                            <property name="digits">2</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">True</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">5</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSeparator">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="TriggerBox">
+                                    <property name="width_request">150</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_left">10</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Triggers</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">L</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">R</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_l">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_r">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">ZL</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">ZR</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_zL">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_zR">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_leftSideTriggerBox">
+                                        <property name="name">_sideTriggerBox</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Left SL</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Left SR</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lSl">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_lSr">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_rightSideTriggerBox">
+                                        <property name="name">_sideTriggerBox</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Right SL</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Right SR</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rSl">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rSr">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_triggerThresholdBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="halign">start</property>
+                                            <property name="margin_left">10</property>
+                                            <property name="label" translatable="yes">Trigger Threshold</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScale">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="adjustment">_controllerTriggerThreshold</property>
+                                            <property name="round_digits">2</property>
+                                            <property name="digits">2</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">True</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_left">10</property>
+                                <child>
+                                  <object class="GtkBox" id="DPadBox">
+                                    <property name="width_request">156</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="margin_top">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Directional Pad</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Dpad Up</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Dpad Down</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Dpad Left</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Dpad Right</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_dpadUp">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_dpadDown">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_dpadLeft">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_dpadRight">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">70</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_rumbleBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="margin_top">10</property>
+                                            <property name="margin_bottom">5</property>
+                                            <property name="label" translatable="yes">Rumble</property>
+                                            <attributes>
+                                              <attribute name="weight" value="bold"/>
+                                            </attributes>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_enableRumble">
+                                            <property name="label" translatable="yes">Enable</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkBox" id="_StrongMultiBox">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="margin_top">10</property>
+                                            <property name="orientation">vertical</property>
+                                            <child>
+                                              <object class="GtkLabel">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">False</property>
+                                                <property name="halign">start</property>
+                                                <property name="label" translatable="yes">Strong rumble multiplier</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">0</property>
+                                              </packing>
+                                            </child>
+                                            <child>
+                                              <object class="GtkScale">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="adjustment">_controllerStrongRumble</property>
+                                                <property name="round_digits">1</property>
+                                                <property name="digits">1</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">True</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">1</property>
+                                              </packing>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkBox" id="_WeakMultiBox">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="margin_top">10</property>
+                                            <property name="orientation">vertical</property>
+                                            <child>
+                                              <object class="GtkLabel">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">False</property>
+                                                <property name="halign">start</property>
+                                                <property name="label" translatable="yes">Weak rumble multiplier</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">0</property>
+                                              </packing>
+                                            </child>
+                                            <child>
+                                              <object class="GtkScale">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="adjustment">_controllerWeakRumble</property>
+                                                <property name="round_digits">1</property>
+                                                <property name="digits">1</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">True</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">1</property>
+                                              </packing>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">3</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSeparator">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="RightStickBox">
+                                    <property name="width_request">160</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_left">10</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Right Stick</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick Button</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStickButton">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_rightStickKeyboard">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick Up</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick Down</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick Left</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick Right</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStickUp">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStickDown">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStickLeft">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStickRight">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">3</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkGrid" id="_rightStickController">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="row_spacing">3</property>
+                                        <property name="column_spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="width_request">80</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">RStick</property>
+                                            <property name="xalign">0</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">0</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkToggleButton" id="_rStick">
+                                            <property name="label" translatable="yes"> </property>
+                                            <property name="width_request">65</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_invertRStickX">
+                                            <property name="label" translatable="yes">Invert Stick X</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_invertRStickY">
+                                            <property name="label" translatable="yes">Invert Stick Y</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_rotateR90CW">
+                                            <property name="label" translatable="yes">Rotate 90° Clockwise</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="top_attach">2</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_deadZoneRightBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="halign">start</property>
+                                            <property name="label" translatable="yes">Deadzone Right</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScale">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="adjustment">_controllerDeadzoneRight</property>
+                                            <property name="round_digits">2</property>
+                                            <property name="digits">2</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">True</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_rangeRightBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="halign">start</property>
+                                            <property name="label" translatable="yes">Range Right</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScale">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="adjustment">_controllerRangeRight</property>
+                                            <property name="round_digits">2</property>
+                                            <property name="digits">2</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">True</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">5</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSeparator">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="_motionBox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_left">10</property>
+                                    <property name="margin_right">10</property>
+                                    <property name="orientation">vertical</property>
+                                    <property name="spacing">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="margin_top">5</property>
+                                        <property name="margin_bottom">5</property>
+                                        <property name="label" translatable="yes">Motion</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" id="_enableMotion">
+                                        <property name="label" translatable="yes">Enable Motion Controls</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="draw_indicator">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" id="_enableCemuHook">
+                                        <property name="label" translatable="yes">Use CemuHook compatible motion</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="draw_indicator">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_motionControllerSlot">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="margin_right">17</property>
+                                            <property name="label" translatable="yes">Controller Slot</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="padding">5</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkSpinButton" id="_slot">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="margin_left">10</property>
+                                            <property name="adjustment">_slotNumber</property>
+                                            <property name="climb_rate">1</property>
+                                            <property name="snap_to_ticks">True</property>
+                                            <property name="numeric">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">10</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="margin_right">5</property>
+                                            <property name="label" translatable="yes">Gyro Sensitivity %</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="padding">5</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkSpinButton">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="text" translatable="yes">0</property>
+                                            <property name="adjustment">_sensitivity</property>
+                                            <property name="climb_rate">1</property>
+                                            <property name="snap_to_ticks">True</property>
+                                            <property name="numeric">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_motionAltBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <object class="GtkCheckButton" id="_mirrorInput">
+                                            <property name="label" translatable="yes">Mirror Input</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkBox">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="spacing">10</property>
+                                            <child>
+                                              <object class="GtkLabel">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">False</property>
+                                                <property name="label" translatable="yes">Right JoyCon Slot</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="padding">5</property>
+                                                <property name="position">0</property>
+                                              </packing>
+                                            </child>
+                                            <child>
+                                              <object class="GtkSpinButton" id="_slotRight">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="text" translatable="yes">0</property>
+                                                <property name="adjustment">_altSlotNumber</property>
+                                                <property name="climb_rate">1</property>
+                                                <property name="snap_to_ticks">True</property>
+                                                <property name="numeric">True</property>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">1</property>
+                                              </packing>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="padding">5</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">5</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_dsuServerHostBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">30</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Server Host</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="padding">5</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkEntry" id="_dsuServerHost">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">6</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkBox" id="_dsuServerPortBox">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">30</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Server Port</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="padding">5</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkEntry" id="_dsuServerPort">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">True</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">7</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="halign">start</property>
+                                        <property name="label" translatable="yes">Gyro Deadzone</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">8</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkScale">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="adjustment">_gyroDeadzone</property>
+                                        <property name="round_digits">2</property>
+                                        <property name="digits">2</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">9</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkImage" id="_controllerImage">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_left">10</property>
+                            <property name="margin_right">20</property>
+                            <property name="margin_top">5</property>
+                            <property name="margin_bottom">5</property>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButtonBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_right">5</property>
+            <property name="margin_top">3</property>
+            <property name="margin_bottom">3</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkToggleButton" id="SaveToggle">
+                <property name="label" translatable="yes">Save</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToggleButton" id="CloseToggle">
+                <property name="label" translatable="yes">Close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="margin_left">4</property>
+                <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">5</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Windows/DlcWindow.cs b/src/Ryujinx/UI/Windows/DlcWindow.cs
new file mode 100644
index 00000000..aed1a015
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/DlcWindow.cs
@@ -0,0 +1,280 @@
+using Gtk;
+using LibHac.Common;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.FsSystem;
+using LibHac.Tools.Fs;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Utilities;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using GUI = Gtk.Builder.ObjectAttribute;
+
+namespace Ryujinx.UI.Windows
+{
+    public class DlcWindow : Window
+    {
+        private readonly VirtualFileSystem _virtualFileSystem;
+        private readonly string _titleId;
+        private readonly string _dlcJsonPath;
+        private readonly List<DownloadableContentContainer> _dlcContainerList;
+
+        private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] Label _baseTitleInfoLabel;
+        [GUI] TreeView _dlcTreeView;
+        [GUI] TreeSelection _dlcTreeSelection;
+#pragma warning restore CS0649, IDE0044
+
+        public DlcWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.UI.Windows.DlcWindow.glade"), virtualFileSystem, titleId, titleName) { }
+
+        private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_dlcWindow"))
+        {
+            builder.Autoconnect(this);
+
+            _titleId = titleId;
+            _virtualFileSystem = virtualFileSystem;
+            _dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json");
+            _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";
+
+            try
+            {
+                _dlcContainerList = JsonHelper.DeserializeFromFile(_dlcJsonPath, _serializerContext.ListDownloadableContentContainer);
+            }
+            catch
+            {
+                _dlcContainerList = new List<DownloadableContentContainer>();
+            }
+
+            _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string));
+
+            CellRendererToggle enableToggle = new();
+            enableToggle.Toggled += (sender, args) =>
+            {
+                _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
+                bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0);
+                _dlcTreeView.Model.SetValue(treeIter, 0, newValue);
+
+                if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
+                {
+                    do
+                    {
+                        _dlcTreeView.Model.SetValue(childIter, 0, newValue);
+                    }
+                    while (_dlcTreeView.Model.IterNext(ref childIter));
+                }
+            };
+
+            _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
+            _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1);
+            _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);
+
+            foreach (DownloadableContentContainer dlcContainer in _dlcContainerList)
+            {
+                if (File.Exists(dlcContainer.ContainerPath))
+                {
+                    // The parent tree item has its own "enabled" check box, but it's the actual
+                    // nca entries that store the enabled / disabled state. A bit of a UI inconsistency.
+                    // Maybe a tri-state check box would be better, but for now we check the parent
+                    // "enabled" box if all child NCAs are enabled. Usually fine since each nsp has only one nca.
+                    bool areAllContentPacksEnabled = dlcContainer.DownloadableContentNcaList.TrueForAll((nca) => nca.Enabled);
+                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(areAllContentPacksEnabled, "", dlcContainer.ContainerPath);
+
+                    using FileStream containerFile = File.OpenRead(dlcContainer.ContainerPath);
+
+                    PartitionFileSystem pfs = new();
+                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
+
+                    _virtualFileSystem.ImportTickets(pfs);
+
+                    foreach (DownloadableContentNca dlcNca in dlcContainer.DownloadableContentNcaList)
+                    {
+                        using var ncaFile = new UniqueRef<IFile>();
+
+                        pfs.OpenFile(ref ncaFile.Ref, dlcNca.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+                        Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), dlcContainer.ContainerPath);
+
+                        if (nca != null)
+                        {
+                            ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.FullPath);
+                        }
+                    }
+                }
+                else
+                {
+                    // DLC file moved or renamed. Allow the user to remove it without crashing the whole dialog.
+                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", $"(MISSING) {dlcContainer.ContainerPath}");
+                }
+            }
+        }
+
+        private Nca TryCreateNca(IStorage ncaStorage, string containerPath)
+        {
+            try
+            {
+                return new Nca(_virtualFileSystem.KeySet, ncaStorage);
+            }
+            catch (Exception exception)
+            {
+                GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {containerPath}");
+            }
+
+            return null;
+        }
+
+        private void AddButton_Clicked(object sender, EventArgs args)
+        {
+            FileChooserNative fileChooser = new("Select DLC files", this, FileChooserAction.Open, "Add", "Cancel")
+            {
+                SelectMultiple = true,
+            };
+
+            FileFilter filter = new()
+            {
+                Name = "Switch Game DLCs",
+            };
+            filter.AddPattern("*.nsp");
+
+            fileChooser.AddFilter(filter);
+
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                foreach (string containerPath in fileChooser.Filenames)
+                {
+                    if (!File.Exists(containerPath))
+                    {
+                        return;
+                    }
+
+                    using FileStream containerFile = File.OpenRead(containerPath);
+
+                    PartitionFileSystem pfs = new();
+                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
+                    bool containsDlc = false;
+
+                    _virtualFileSystem.ImportTickets(pfs);
+
+                    TreeIter? parentIter = null;
+
+                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
+                    {
+                        using var ncaFile = new UniqueRef<IFile>();
+
+                        pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+                        Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), containerPath);
+
+                        if (nca == null)
+                        {
+                            continue;
+                        }
+
+                        if (nca.Header.ContentType == NcaContentType.PublicData)
+                        {
+                            if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000).ToString("x16") != _titleId)
+                            {
+                                break;
+                            }
+
+                            parentIter ??= ((TreeStore)_dlcTreeView.Model).AppendValues(true, "", containerPath);
+
+                            ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter.Value, true, nca.Header.TitleId.ToString("X16"), fileEntry.FullPath);
+                            containsDlc = true;
+                        }
+                    }
+
+                    if (!containsDlc)
+                    {
+                        GtkDialog.CreateErrorDialog("The specified file does not contain DLC for the selected title!");
+                    }
+                }
+            }
+
+            fileChooser.Dispose();
+        }
+
+        private void RemoveButton_Clicked(object sender, EventArgs args)
+        {
+            if (_dlcTreeSelection.GetSelected(out ITreeModel treeModel, out TreeIter treeIter))
+            {
+                if (_dlcTreeView.Model.IterParent(out TreeIter parentIter, treeIter) && _dlcTreeView.Model.IterNChildren(parentIter) <= 1)
+                {
+                    ((TreeStore)treeModel).Remove(ref parentIter);
+                }
+                else
+                {
+                    ((TreeStore)treeModel).Remove(ref treeIter);
+                }
+            }
+        }
+
+        private void RemoveAllButton_Clicked(object sender, EventArgs args)
+        {
+            List<TreeIter> toRemove = new();
+
+            if (_dlcTreeView.Model.GetIterFirst(out TreeIter iter))
+            {
+                do
+                {
+                    toRemove.Add(iter);
+                }
+                while (_dlcTreeView.Model.IterNext(ref iter));
+            }
+
+            foreach (TreeIter i in toRemove)
+            {
+                TreeIter j = i;
+                ((TreeStore)_dlcTreeView.Model).Remove(ref j);
+            }
+        }
+
+        private void SaveButton_Clicked(object sender, EventArgs args)
+        {
+            _dlcContainerList.Clear();
+
+            if (_dlcTreeView.Model.GetIterFirst(out TreeIter parentIter))
+            {
+                do
+                {
+                    if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, parentIter))
+                    {
+                        DownloadableContentContainer dlcContainer = new()
+                        {
+                            ContainerPath = (string)_dlcTreeView.Model.GetValue(parentIter, 2),
+                            DownloadableContentNcaList = new List<DownloadableContentNca>(),
+                        };
+
+                        do
+                        {
+                            dlcContainer.DownloadableContentNcaList.Add(new DownloadableContentNca
+                            {
+                                Enabled = (bool)_dlcTreeView.Model.GetValue(childIter, 0),
+                                TitleId = Convert.ToUInt64(_dlcTreeView.Model.GetValue(childIter, 1).ToString(), 16),
+                                FullPath = (string)_dlcTreeView.Model.GetValue(childIter, 2),
+                            });
+                        }
+                        while (_dlcTreeView.Model.IterNext(ref childIter));
+
+                        _dlcContainerList.Add(dlcContainer);
+                    }
+                }
+                while (_dlcTreeView.Model.IterNext(ref parentIter));
+            }
+
+            JsonHelper.SerializeToFile(_dlcJsonPath, _dlcContainerList, _serializerContext.ListDownloadableContentContainer);
+
+            Dispose();
+        }
+
+        private void CancelButton_Clicked(object sender, EventArgs args)
+        {
+            Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/DlcWindow.glade b/src/Ryujinx/UI/Windows/DlcWindow.glade
new file mode 100644
index 00000000..bdb0e647
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/DlcWindow.glade
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkWindow" id="_dlcWindow">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - DLC Manager</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="default_width">550</property>
+    <property name="default_height">350</property>
+    <child>
+      <object class="GtkBox" id="MainBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkBox" id="DlcBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel" id="_baseTitleInfoLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="label" translatable="yes">Available DLC</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTreeView" id="_dlcTreeView">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="headers_clickable">False</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="_dlcTreeSelection"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="layout_style">start</property>
+                <child>
+                  <object class="GtkButton" id="_addUpdate">
+                    <property name="label" translatable="yes">Add</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Adds a DLC to this list</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="AddButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_removeUpdate">
+                    <property name="label" translatable="yes">Remove</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Removes the selected DLC</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="RemoveButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_removeAllButton">
+                    <property name="label" translatable="yes">Remove All</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Removes all DLCs</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="RemoveAllButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <object class="GtkButton" id="_saveButton">
+                    <property name="label" translatable="yes">Save</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_cancelButton">
+                    <property name="label" translatable="yes">Cancel</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.cs b/src/Ryujinx/UI/Windows/SettingsWindow.cs
new file mode 100644
index 00000000..270a8ad4
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/SettingsWindow.cs
@@ -0,0 +1,847 @@
+using Gtk;
+using LibHac.Tools.FsSystem;
+using Ryujinx.Audio.Backends.OpenAL;
+using Ryujinx.Audio.Backends.SDL2;
+using Ryujinx.Audio.Backends.SoundIo;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Multiplayer;
+using Ryujinx.Common.GraphicsDriver;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS.Services.Time.TimeZone;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Common.Configuration.System;
+using Ryujinx.UI.Helper;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Net.NetworkInformation;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using GUI = Gtk.Builder.ObjectAttribute;
+
+namespace Ryujinx.UI.Windows
+{
+    public class SettingsWindow : Window
+    {
+        private readonly MainWindow _parent;
+        private readonly ListStore _gameDirsBoxStore;
+        private readonly ListStore _audioBackendStore;
+        private readonly TimeZoneContentManager _timeZoneContentManager;
+        private readonly HashSet<string> _validTzRegions;
+
+        private long _systemTimeOffset;
+        private float _previousVolumeLevel;
+        private bool _directoryChanged = false;
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] CheckButton _traceLogToggle;
+        [GUI] CheckButton _errorLogToggle;
+        [GUI] CheckButton _warningLogToggle;
+        [GUI] CheckButton _infoLogToggle;
+        [GUI] CheckButton _stubLogToggle;
+        [GUI] CheckButton _debugLogToggle;
+        [GUI] CheckButton _fileLogToggle;
+        [GUI] CheckButton _guestLogToggle;
+        [GUI] CheckButton _fsAccessLogToggle;
+        [GUI] Adjustment _fsLogSpinAdjustment;
+        [GUI] ComboBoxText _graphicsDebugLevel;
+        [GUI] CheckButton _dockedModeToggle;
+        [GUI] CheckButton _discordToggle;
+        [GUI] CheckButton _checkUpdatesToggle;
+        [GUI] CheckButton _showConfirmExitToggle;
+        [GUI] RadioButton _hideCursorNever;
+        [GUI] RadioButton _hideCursorOnIdle;
+        [GUI] RadioButton _hideCursorAlways;
+        [GUI] CheckButton _vSyncToggle;
+        [GUI] CheckButton _shaderCacheToggle;
+        [GUI] CheckButton _textureRecompressionToggle;
+        [GUI] CheckButton _macroHLEToggle;
+        [GUI] CheckButton _ptcToggle;
+        [GUI] CheckButton _internetToggle;
+        [GUI] CheckButton _fsicToggle;
+        [GUI] RadioButton _mmSoftware;
+        [GUI] RadioButton _mmHost;
+        [GUI] RadioButton _mmHostUnsafe;
+        [GUI] CheckButton _expandRamToggle;
+        [GUI] CheckButton _ignoreToggle;
+        [GUI] CheckButton _directKeyboardAccess;
+        [GUI] CheckButton _directMouseAccess;
+        [GUI] ComboBoxText _systemLanguageSelect;
+        [GUI] ComboBoxText _systemRegionSelect;
+        [GUI] Entry _systemTimeZoneEntry;
+        [GUI] EntryCompletion _systemTimeZoneCompletion;
+        [GUI] Box _audioBackendBox;
+        [GUI] ComboBox _audioBackendSelect;
+        [GUI] Label _audioVolumeLabel;
+        [GUI] Scale _audioVolumeSlider;
+        [GUI] SpinButton _systemTimeYearSpin;
+        [GUI] SpinButton _systemTimeMonthSpin;
+        [GUI] SpinButton _systemTimeDaySpin;
+        [GUI] SpinButton _systemTimeHourSpin;
+        [GUI] SpinButton _systemTimeMinuteSpin;
+        [GUI] Adjustment _systemTimeYearSpinAdjustment;
+        [GUI] Adjustment _systemTimeMonthSpinAdjustment;
+        [GUI] Adjustment _systemTimeDaySpinAdjustment;
+        [GUI] Adjustment _systemTimeHourSpinAdjustment;
+        [GUI] Adjustment _systemTimeMinuteSpinAdjustment;
+        [GUI] ComboBoxText _multiLanSelect;
+        [GUI] ComboBoxText _multiModeSelect;
+        [GUI] CheckButton _custThemeToggle;
+        [GUI] Entry _custThemePath;
+        [GUI] ToggleButton _browseThemePath;
+        [GUI] Label _custThemePathLabel;
+        [GUI] TreeView _gameDirsBox;
+        [GUI] Entry _addGameDirBox;
+        [GUI] ComboBoxText _galThreading;
+        [GUI] Entry _graphicsShadersDumpPath;
+        [GUI] ComboBoxText _anisotropy;
+        [GUI] ComboBoxText _aspectRatio;
+        [GUI] ComboBoxText _antiAliasing;
+        [GUI] ComboBoxText _scalingFilter;
+        [GUI] ComboBoxText _graphicsBackend;
+        [GUI] ComboBoxText _preferredGpu;
+        [GUI] ComboBoxText _resScaleCombo;
+        [GUI] Entry _resScaleText;
+        [GUI] Adjustment _scalingFilterLevel;
+        [GUI] Scale _scalingFilterSlider;
+        [GUI] ToggleButton _configureController1;
+        [GUI] ToggleButton _configureController2;
+        [GUI] ToggleButton _configureController3;
+        [GUI] ToggleButton _configureController4;
+        [GUI] ToggleButton _configureController5;
+        [GUI] ToggleButton _configureController6;
+        [GUI] ToggleButton _configureController7;
+        [GUI] ToggleButton _configureController8;
+        [GUI] ToggleButton _configureControllerH;
+
+#pragma warning restore CS0649, IDE0044
+
+        public SettingsWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(parent, new Builder("Ryujinx.UI.Windows.SettingsWindow.glade"), virtualFileSystem, contentManager) { }
+
+        private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : base(builder.GetRawOwnedObject("_settingsWin"))
+        {
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            _parent = parent;
+
+            builder.Autoconnect(this);
+
+            _timeZoneContentManager = new TimeZoneContentManager();
+            _timeZoneContentManager.InitializeInstance(virtualFileSystem, contentManager, IntegrityCheckLevel.None);
+
+            _validTzRegions = new HashSet<string>(_timeZoneContentManager.LocationNameCache.Length, StringComparer.Ordinal); // Zone regions are identifiers. Must match exactly.
+
+            // Bind Events.
+            _configureController1.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player1);
+            _configureController2.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player2);
+            _configureController3.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player3);
+            _configureController4.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player4);
+            _configureController5.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player5);
+            _configureController6.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player6);
+            _configureController7.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player7);
+            _configureController8.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player8);
+            _configureControllerH.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Handheld);
+            _systemTimeZoneEntry.FocusOutEvent += TimeZoneEntry_FocusOut;
+
+            _resScaleCombo.Changed += (sender, args) => _resScaleText.Visible = _resScaleCombo.ActiveId == "-1";
+            _scalingFilter.Changed += (sender, args) => _scalingFilterSlider.Visible = _scalingFilter.ActiveId == "2";
+            _galThreading.Changed += (sender, args) =>
+            {
+                if (_galThreading.ActiveId != ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString())
+                {
+                    GtkDialog.CreateInfoDialog("Warning - Backend Threading", "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.");
+                }
+            };
+
+            // Setup Currents.
+            if (ConfigurationState.Instance.Logger.EnableTrace)
+            {
+                _traceLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableFileLog)
+            {
+                _fileLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableError)
+            {
+                _errorLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableWarn)
+            {
+                _warningLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableInfo)
+            {
+                _infoLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableStub)
+            {
+                _stubLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableDebug)
+            {
+                _debugLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableGuest)
+            {
+                _guestLogToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Logger.EnableFsAccessLog)
+            {
+                _fsAccessLogToggle.Click();
+            }
+
+            foreach (GraphicsDebugLevel level in Enum.GetValues<GraphicsDebugLevel>())
+            {
+                _graphicsDebugLevel.Append(level.ToString(), level.ToString());
+            }
+
+            _graphicsDebugLevel.SetActiveId(ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value.ToString());
+
+            if (ConfigurationState.Instance.System.EnableDockedMode)
+            {
+                _dockedModeToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.EnableDiscordIntegration)
+            {
+                _discordToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.CheckUpdatesOnStart)
+            {
+                _checkUpdatesToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.ShowConfirmExit)
+            {
+                _showConfirmExitToggle.Click();
+            }
+
+            switch (ConfigurationState.Instance.HideCursor.Value)
+            {
+                case HideCursorMode.Never:
+                    _hideCursorNever.Click();
+                    break;
+                case HideCursorMode.OnIdle:
+                    _hideCursorOnIdle.Click();
+                    break;
+                case HideCursorMode.Always:
+                    _hideCursorAlways.Click();
+                    break;
+            }
+
+            if (ConfigurationState.Instance.Graphics.EnableVsync)
+            {
+                _vSyncToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Graphics.EnableShaderCache)
+            {
+                _shaderCacheToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Graphics.EnableTextureRecompression)
+            {
+                _textureRecompressionToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Graphics.EnableMacroHLE)
+            {
+                _macroHLEToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.System.EnablePtc)
+            {
+                _ptcToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.System.EnableInternetAccess)
+            {
+                _internetToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.System.EnableFsIntegrityChecks)
+            {
+                _fsicToggle.Click();
+            }
+
+            switch (ConfigurationState.Instance.System.MemoryManagerMode.Value)
+            {
+                case MemoryManagerMode.SoftwarePageTable:
+                    _mmSoftware.Click();
+                    break;
+                case MemoryManagerMode.HostMapped:
+                    _mmHost.Click();
+                    break;
+                case MemoryManagerMode.HostMappedUnsafe:
+                    _mmHostUnsafe.Click();
+                    break;
+            }
+
+            if (ConfigurationState.Instance.System.ExpandRam)
+            {
+                _expandRamToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.System.IgnoreMissingServices)
+            {
+                _ignoreToggle.Click();
+            }
+
+            if (ConfigurationState.Instance.Hid.EnableKeyboard)
+            {
+                _directKeyboardAccess.Click();
+            }
+
+            if (ConfigurationState.Instance.Hid.EnableMouse)
+            {
+                _directMouseAccess.Click();
+            }
+
+            if (ConfigurationState.Instance.UI.EnableCustomTheme)
+            {
+                _custThemeToggle.Click();
+            }
+
+            // Custom EntryCompletion Columns. If added to glade, need to override more signals
+            ListStore tzList = new(typeof(string), typeof(string), typeof(string));
+            _systemTimeZoneCompletion.Model = tzList;
+
+            CellRendererText offsetCol = new();
+            CellRendererText abbrevCol = new();
+
+            _systemTimeZoneCompletion.PackStart(offsetCol, false);
+            _systemTimeZoneCompletion.AddAttribute(offsetCol, "text", 0);
+            _systemTimeZoneCompletion.TextColumn = 1; // Regions Column
+            _systemTimeZoneCompletion.PackStart(abbrevCol, false);
+            _systemTimeZoneCompletion.AddAttribute(abbrevCol, "text", 2);
+
+            int maxLocationLength = 0;
+
+            foreach (var (offset, location, abbr) in _timeZoneContentManager.ParseTzOffsets())
+            {
+                var hours = Math.DivRem(offset, 3600, out int seconds);
+                var minutes = Math.Abs(seconds) / 60;
+
+                var abbr2 = (abbr.StartsWith('+') || abbr.StartsWith('-')) ? string.Empty : abbr;
+
+                tzList.AppendValues($"UTC{hours:+0#;-0#;+00}:{minutes:D2} ", location, abbr2);
+                _validTzRegions.Add(location);
+
+                maxLocationLength = Math.Max(maxLocationLength, location.Length);
+            }
+
+            _systemTimeZoneEntry.WidthChars = Math.Max(20, maxLocationLength + 1); // Ensure minimum Entry width
+            _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
+
+            _systemTimeZoneCompletion.MatchFunc = TimeZoneMatchFunc;
+
+            _systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString());
+            _systemRegionSelect.SetActiveId(ConfigurationState.Instance.System.Region.Value.ToString());
+            _galThreading.SetActiveId(ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString());
+            _resScaleCombo.SetActiveId(ConfigurationState.Instance.Graphics.ResScale.Value.ToString());
+            _anisotropy.SetActiveId(ConfigurationState.Instance.Graphics.MaxAnisotropy.Value.ToString());
+            _aspectRatio.SetActiveId(((int)ConfigurationState.Instance.Graphics.AspectRatio.Value).ToString());
+            _graphicsBackend.SetActiveId(((int)ConfigurationState.Instance.Graphics.GraphicsBackend.Value).ToString());
+            _antiAliasing.SetActiveId(((int)ConfigurationState.Instance.Graphics.AntiAliasing.Value).ToString());
+            _scalingFilter.SetActiveId(((int)ConfigurationState.Instance.Graphics.ScalingFilter.Value).ToString());
+
+            UpdatePreferredGpuComboBox();
+
+            _graphicsBackend.Changed += (sender, e) => UpdatePreferredGpuComboBox();
+            PopulateNetworkInterfaces();
+            _multiLanSelect.SetActiveId(ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value);
+            _multiModeSelect.SetActiveId(ConfigurationState.Instance.Multiplayer.Mode.Value.ToString());
+
+            _custThemePath.Buffer.Text = ConfigurationState.Instance.UI.CustomThemePath;
+            _resScaleText.Buffer.Text = ConfigurationState.Instance.Graphics.ResScaleCustom.Value.ToString();
+            _scalingFilterLevel.Value = ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value;
+            _resScaleText.Visible = _resScaleCombo.ActiveId == "-1";
+            _scalingFilterSlider.Visible = _scalingFilter.ActiveId == "2";
+            _graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath;
+            _fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode;
+            _systemTimeOffset = ConfigurationState.Instance.System.SystemTimeOffset;
+
+            _gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0);
+            _gameDirsBoxStore = new ListStore(typeof(string));
+            _gameDirsBox.Model = _gameDirsBoxStore;
+
+            foreach (string gameDir in ConfigurationState.Instance.UI.GameDirs.Value)
+            {
+                _gameDirsBoxStore.AppendValues(gameDir);
+            }
+
+            if (_custThemeToggle.Active == false)
+            {
+                _custThemePath.Sensitive = false;
+                _custThemePathLabel.Sensitive = false;
+                _browseThemePath.Sensitive = false;
+            }
+
+            // Setup system time spinners
+            UpdateSystemTimeSpinners();
+
+            _audioBackendStore = new ListStore(typeof(string), typeof(AudioBackend));
+
+            TreeIter openAlIter = _audioBackendStore.AppendValues("OpenAL", AudioBackend.OpenAl);
+            TreeIter soundIoIter = _audioBackendStore.AppendValues("SoundIO", AudioBackend.SoundIo);
+            TreeIter sdl2Iter = _audioBackendStore.AppendValues("SDL2", AudioBackend.SDL2);
+            TreeIter dummyIter = _audioBackendStore.AppendValues("Dummy", AudioBackend.Dummy);
+
+            _audioBackendSelect = ComboBox.NewWithModelAndEntry(_audioBackendStore);
+            _audioBackendSelect.EntryTextColumn = 0;
+            _audioBackendSelect.Entry.IsEditable = false;
+
+            switch (ConfigurationState.Instance.System.AudioBackend.Value)
+            {
+                case AudioBackend.OpenAl:
+                    _audioBackendSelect.SetActiveIter(openAlIter);
+                    break;
+                case AudioBackend.SoundIo:
+                    _audioBackendSelect.SetActiveIter(soundIoIter);
+                    break;
+                case AudioBackend.SDL2:
+                    _audioBackendSelect.SetActiveIter(sdl2Iter);
+                    break;
+                case AudioBackend.Dummy:
+                    _audioBackendSelect.SetActiveIter(dummyIter);
+                    break;
+                default:
+                    throw new InvalidOperationException($"{nameof(ConfigurationState.Instance.System.AudioBackend)} contains an invalid value: {ConfigurationState.Instance.System.AudioBackend.Value}");
+            }
+
+            _audioBackendBox.Add(_audioBackendSelect);
+            _audioBackendSelect.Show();
+
+            _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume;
+            _audioVolumeLabel = new Label("Volume: ");
+            _audioVolumeSlider = new Scale(Orientation.Horizontal, 0, 100, 1);
+            _audioVolumeLabel.MarginStart = 10;
+            _audioVolumeSlider.ValuePos = PositionType.Right;
+            _audioVolumeSlider.WidthRequest = 200;
+
+            _audioVolumeSlider.Value = _previousVolumeLevel * 100;
+            _audioVolumeSlider.ValueChanged += VolumeSlider_OnChange;
+            _audioBackendBox.Add(_audioVolumeLabel);
+            _audioBackendBox.Add(_audioVolumeSlider);
+            _audioVolumeLabel.Show();
+            _audioVolumeSlider.Show();
+
+            bool openAlIsSupported = false;
+            bool soundIoIsSupported = false;
+            bool sdl2IsSupported = false;
+
+            Task.Run(() =>
+            {
+                openAlIsSupported = OpenALHardwareDeviceDriver.IsSupported;
+                soundIoIsSupported = !OperatingSystem.IsMacOS() && SoundIoHardwareDeviceDriver.IsSupported;
+                sdl2IsSupported = SDL2HardwareDeviceDriver.IsSupported;
+            });
+
+            // This function runs whenever the dropdown is opened
+            _audioBackendSelect.SetCellDataFunc(_audioBackendSelect.Cells[0], (layout, cell, model, iter) =>
+            {
+                cell.Sensitive = ((AudioBackend)_audioBackendStore.GetValue(iter, 1)) switch
+                {
+                    AudioBackend.OpenAl => openAlIsSupported,
+                    AudioBackend.SoundIo => soundIoIsSupported,
+                    AudioBackend.SDL2 => sdl2IsSupported,
+                    AudioBackend.Dummy => true,
+                    _ => throw new InvalidOperationException($"{nameof(_audioBackendStore)} contains an invalid value for iteration {iter}: {_audioBackendStore.GetValue(iter, 1)}"),
+                };
+            });
+
+            if (OperatingSystem.IsMacOS())
+            {
+                var store = (_graphicsBackend.Model as ListStore);
+                store.GetIter(out TreeIter openglIter, new TreePath(new[] { 1 }));
+                store.Remove(ref openglIter);
+
+                _graphicsBackend.Model = store;
+            }
+        }
+
+        private void UpdatePreferredGpuComboBox()
+        {
+            _preferredGpu.RemoveAll();
+
+            if (Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId) == GraphicsBackend.Vulkan)
+            {
+                var devices = Graphics.Vulkan.VulkanRenderer.GetPhysicalDevices();
+                string preferredGpuIdFromConfig = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
+                string preferredGpuId = preferredGpuIdFromConfig;
+                bool noGpuId = string.IsNullOrEmpty(preferredGpuIdFromConfig);
+
+                foreach (var device in devices)
+                {
+                    string dGpu = device.IsDiscrete ? " (dGPU)" : "";
+                    _preferredGpu.Append(device.Id, $"{device.Name}{dGpu}");
+
+                    // If there's no GPU selected yet, we just pick the first GPU.
+                    // If there's a discrete GPU available, we always prefer that over the previous selection,
+                    // as it is likely to have better performance and more features.
+                    // If the configuration file already has a GPU selection, we always prefer that instead.
+                    if (noGpuId && (string.IsNullOrEmpty(preferredGpuId) || device.IsDiscrete))
+                    {
+                        preferredGpuId = device.Id;
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(preferredGpuId))
+                {
+                    _preferredGpu.SetActiveId(preferredGpuId);
+                }
+            }
+        }
+
+        private void PopulateNetworkInterfaces()
+        {
+            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
+
+            foreach (NetworkInterface nif in interfaces)
+            {
+                string guid = nif.Id;
+                string name = nif.Name;
+
+                _multiLanSelect.Append(guid, name);
+            }
+        }
+
+        private void UpdateSystemTimeSpinners()
+        {
+            //Bind system time events
+            _systemTimeYearSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+            _systemTimeMonthSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+            _systemTimeDaySpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+            _systemTimeHourSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+            _systemTimeMinuteSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+
+            //Apply actual system time + SystemTimeOffset to system time spin buttons
+            DateTime systemTime = DateTime.Now.AddSeconds(_systemTimeOffset);
+
+            _systemTimeYearSpinAdjustment.Value = systemTime.Year;
+            _systemTimeMonthSpinAdjustment.Value = systemTime.Month;
+            _systemTimeDaySpinAdjustment.Value = systemTime.Day;
+            _systemTimeHourSpinAdjustment.Value = systemTime.Hour;
+            _systemTimeMinuteSpinAdjustment.Value = systemTime.Minute;
+
+            //Format spin buttons text to include leading zeros
+            _systemTimeYearSpin.Text = systemTime.Year.ToString("0000");
+            _systemTimeMonthSpin.Text = systemTime.Month.ToString("00");
+            _systemTimeDaySpin.Text = systemTime.Day.ToString("00");
+            _systemTimeHourSpin.Text = systemTime.Hour.ToString("00");
+            _systemTimeMinuteSpin.Text = systemTime.Minute.ToString("00");
+
+            //Bind system time events
+            _systemTimeYearSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+            _systemTimeMonthSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+            _systemTimeDaySpin.ValueChanged += SystemTimeSpin_ValueChanged;
+            _systemTimeHourSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+            _systemTimeMinuteSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+        }
+
+        private void SaveSettings()
+        {
+            if (_directoryChanged)
+            {
+                List<string> gameDirs = new();
+
+                _gameDirsBoxStore.GetIterFirst(out TreeIter treeIter);
+
+                for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++)
+                {
+                    gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0));
+
+                    _gameDirsBoxStore.IterNext(ref treeIter);
+                }
+
+                ConfigurationState.Instance.UI.GameDirs.Value = gameDirs;
+
+                _directoryChanged = false;
+            }
+
+            HideCursorMode hideCursor = HideCursorMode.Never;
+
+            if (_hideCursorOnIdle.Active)
+            {
+                hideCursor = HideCursorMode.OnIdle;
+            }
+
+            if (_hideCursorAlways.Active)
+            {
+                hideCursor = HideCursorMode.Always;
+            }
+
+            if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f)
+            {
+                resScaleCustom = 1.0f;
+            }
+
+            if (_validTzRegions.Contains(_systemTimeZoneEntry.Text))
+            {
+                ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneEntry.Text;
+            }
+
+            MemoryManagerMode memoryMode = MemoryManagerMode.SoftwarePageTable;
+
+            if (_mmHost.Active)
+            {
+                memoryMode = MemoryManagerMode.HostMapped;
+            }
+
+            if (_mmHostUnsafe.Active)
+            {
+                memoryMode = MemoryManagerMode.HostMappedUnsafe;
+            }
+
+            BackendThreading backendThreading = Enum.Parse<BackendThreading>(_galThreading.ActiveId);
+            if (ConfigurationState.Instance.Graphics.BackendThreading != backendThreading)
+            {
+                DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off);
+            }
+
+            ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active;
+            ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active;
+            ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId);
+            ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
+            ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
+            ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
+            ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active;
+            ConfigurationState.Instance.HideCursor.Value = hideCursor;
+            ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
+            ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
+            ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
+            ConfigurationState.Instance.Graphics.EnableMacroHLE.Value = _macroHLEToggle.Active;
+            ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
+            ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
+            ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
+            ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode;
+            ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active;
+            ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active;
+            ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active;
+            ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active;
+            ConfigurationState.Instance.UI.EnableCustomTheme.Value = _custThemeToggle.Active;
+            ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId);
+            ConfigurationState.Instance.System.Region.Value = Enum.Parse<Common.Configuration.System.Region>(_systemRegionSelect.ActiveId);
+            ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
+            ConfigurationState.Instance.UI.CustomThemePath.Value = _custThemePath.Buffer.Text;
+            ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
+            ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
+            ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture);
+            ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
+            ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading;
+            ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId);
+            ConfigurationState.Instance.Graphics.PreferredGpu.Value = _preferredGpu.ActiveId;
+            ConfigurationState.Instance.Graphics.ResScale.Value = int.Parse(_resScaleCombo.ActiveId);
+            ConfigurationState.Instance.Graphics.ResScaleCustom.Value = resScaleCustom;
+            ConfigurationState.Instance.System.AudioVolume.Value = (float)_audioVolumeSlider.Value / 100.0f;
+            ConfigurationState.Instance.Graphics.AntiAliasing.Value = Enum.Parse<AntiAliasing>(_antiAliasing.ActiveId);
+            ConfigurationState.Instance.Graphics.ScalingFilter.Value = Enum.Parse<ScalingFilter>(_scalingFilter.ActiveId);
+            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value = (int)_scalingFilterLevel.Value;
+            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _multiLanSelect.ActiveId;
+
+            _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume.Value;
+
+            ConfigurationState.Instance.Multiplayer.Mode.Value = Enum.Parse<MultiplayerMode>(_multiModeSelect.ActiveId);
+            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _multiLanSelect.ActiveId;
+
+            if (_audioBackendSelect.GetActiveIter(out TreeIter activeIter))
+            {
+                ConfigurationState.Instance.System.AudioBackend.Value = (AudioBackend)_audioBackendStore.GetValue(activeIter, 1);
+            }
+
+            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+
+            _parent.UpdateInternetAccess();
+            MainWindow.UpdateGraphicsConfig();
+            ThemeHelper.ApplyTheme();
+        }
+
+        //
+        // Events
+        //
+        private void TimeZoneEntry_FocusOut(object sender, FocusOutEventArgs e)
+        {
+            if (!_validTzRegions.Contains(_systemTimeZoneEntry.Text))
+            {
+                _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
+            }
+        }
+
+        private bool TimeZoneMatchFunc(EntryCompletion compl, string key, TreeIter iter)
+        {
+            key = key.Trim().Replace(' ', '_');
+
+            return ((string)compl.Model.GetValue(iter, 1)).Contains(key, StringComparison.OrdinalIgnoreCase) || // region
+                   ((string)compl.Model.GetValue(iter, 2)).StartsWith(key, StringComparison.OrdinalIgnoreCase) || // abbr
+                   ((string)compl.Model.GetValue(iter, 0))[3..].StartsWith(key); // offset
+        }
+
+        private void SystemTimeSpin_ValueChanged(object sender, EventArgs e)
+        {
+            int year = _systemTimeYearSpin.ValueAsInt;
+            int month = _systemTimeMonthSpin.ValueAsInt;
+            int day = _systemTimeDaySpin.ValueAsInt;
+            int hour = _systemTimeHourSpin.ValueAsInt;
+            int minute = _systemTimeMinuteSpin.ValueAsInt;
+
+            if (!DateTime.TryParse(year + "-" + month + "-" + day + " " + hour + ":" + minute, out DateTime newTime))
+            {
+                UpdateSystemTimeSpinners();
+
+                return;
+            }
+
+            newTime = newTime.AddSeconds(DateTime.Now.Second).AddMilliseconds(DateTime.Now.Millisecond);
+
+            long systemTimeOffset = (long)Math.Ceiling((newTime - DateTime.Now).TotalMinutes) * 60L;
+
+            if (_systemTimeOffset != systemTimeOffset)
+            {
+                _systemTimeOffset = systemTimeOffset;
+                UpdateSystemTimeSpinners();
+            }
+        }
+
+        private void AddDir_Pressed(object sender, EventArgs args)
+        {
+            if (Directory.Exists(_addGameDirBox.Buffer.Text))
+            {
+                _gameDirsBoxStore.AppendValues(_addGameDirBox.Buffer.Text);
+                _directoryChanged = true;
+            }
+            else
+            {
+                FileChooserNative fileChooser = new("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Add", "Cancel")
+                {
+                    SelectMultiple = true,
+                };
+
+                if (fileChooser.Run() == (int)ResponseType.Accept)
+                {
+                    _directoryChanged = false;
+                    foreach (string directory in fileChooser.Filenames)
+                    {
+                        if (_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter))
+                        {
+                            do
+                            {
+                                if (directory.Equals((string)_gameDirsBoxStore.GetValue(treeIter, 0)))
+                                {
+                                    break;
+                                }
+                            } while (_gameDirsBoxStore.IterNext(ref treeIter));
+                        }
+
+                        if (!_directoryChanged)
+                        {
+                            _gameDirsBoxStore.AppendValues(directory);
+                        }
+                    }
+
+                    _directoryChanged = true;
+                }
+
+                fileChooser.Dispose();
+            }
+
+            _addGameDirBox.Buffer.Text = "";
+
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+        }
+
+        private void RemoveDir_Pressed(object sender, EventArgs args)
+        {
+            TreeSelection selection = _gameDirsBox.Selection;
+
+            if (selection.GetSelected(out TreeIter treeIter))
+            {
+                _gameDirsBoxStore.Remove(ref treeIter);
+
+                _directoryChanged = true;
+            }
+
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+        }
+
+        private void CustThemeToggle_Activated(object sender, EventArgs args)
+        {
+            _custThemePath.Sensitive = _custThemeToggle.Active;
+            _custThemePathLabel.Sensitive = _custThemeToggle.Active;
+            _browseThemePath.Sensitive = _custThemeToggle.Active;
+        }
+
+        private void BrowseThemeDir_Pressed(object sender, EventArgs args)
+        {
+            using (FileChooserNative fileChooser = new("Choose the theme to load", this, FileChooserAction.Open, "Select", "Cancel"))
+            {
+                FileFilter filter = new()
+                {
+                    Name = "Theme Files",
+                };
+                filter.AddPattern("*.css");
+
+                fileChooser.AddFilter(filter);
+
+                if (fileChooser.Run() == (int)ResponseType.Accept)
+                {
+                    _custThemePath.Buffer.Text = fileChooser.Filename;
+                }
+            }
+
+            _browseThemePath.SetStateFlags(StateFlags.Normal, true);
+        }
+
+        private void ConfigureController_Pressed(object sender, PlayerIndex playerIndex)
+        {
+            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
+
+            ControllerWindow controllerWindow = new(_parent, playerIndex);
+
+            controllerWindow.SetSizeRequest((int)(controllerWindow.DefaultWidth * Program.WindowScaleFactor), (int)(controllerWindow.DefaultHeight * Program.WindowScaleFactor));
+            controllerWindow.Show();
+        }
+
+        private void VolumeSlider_OnChange(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.System.AudioVolume.Value = (float)(_audioVolumeSlider.Value / 100);
+        }
+
+        private void SaveToggle_Activated(object sender, EventArgs args)
+        {
+            SaveSettings();
+            Dispose();
+        }
+
+        private void ApplyToggle_Activated(object sender, EventArgs args)
+        {
+            SaveSettings();
+        }
+
+        private void CloseToggle_Activated(object sender, EventArgs args)
+        {
+            ConfigurationState.Instance.System.AudioVolume.Value = _previousVolumeLevel;
+            Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.glade b/src/Ryujinx/UI/Windows/SettingsWindow.glade
new file mode 100644
index 00000000..f0dbd6b6
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/SettingsWindow.glade
@@ -0,0 +1,3221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkAdjustment" id="_fsLogSpinAdjustment">
+    <property name="upper">3</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="_scalingFilterLevel">
+    <property name="upper">101</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">5</property>
+    <property name="page-size">1</property>
+  </object>
+  <object class="GtkAdjustment" id="_systemTimeDaySpinAdjustment">
+    <property name="lower">1</property>
+    <property name="upper">31</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">5</property>
+  </object>
+  <object class="GtkAdjustment" id="_systemTimeHourSpinAdjustment">
+    <property name="upper">23</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">5</property>
+  </object>
+  <object class="GtkAdjustment" id="_systemTimeMinuteSpinAdjustment">
+    <property name="upper">59</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">5</property>
+  </object>
+  <object class="GtkAdjustment" id="_systemTimeMonthSpinAdjustment">
+    <property name="lower">1</property>
+    <property name="upper">12</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">5</property>
+  </object>
+  <object class="GtkAdjustment" id="_systemTimeYearSpinAdjustment">
+    <property name="lower">2000</property>
+    <property name="upper">2060</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">10</property>
+  </object>
+  <object class="GtkEntryCompletion" id="_systemTimeZoneCompletion">
+    <property name="minimum-key-length">0</property>
+    <property name="inline-completion">True</property>
+    <property name="inline-selection">True</property>
+  </object>
+  <object class="GtkWindow" id="_settingsWin">
+    <property name="can-focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - Settings</property>
+    <property name="modal">True</property>
+    <property name="window-position">center</property>
+    <property name="default-width">650</property>
+    <property name="default-height">650</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="shadow-type">in</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <object class="GtkNotebook">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <child>
+                      <object class="GtkBox" id="TabGeneral">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">10</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox" id="CatGeneral">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">General</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="General">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="_discordToggle">
+                                    <property name="label" translatable="yes">Enable Discord Rich Presence</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Choose whether or not to display Ryujinx on your "currently playing" Discord activity</property>
+                                    <property name="halign">start</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_checkUpdatesToggle">
+                                    <property name="label" translatable="yes">Check for Updates on Launch</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_showConfirmExitToggle">
+                                    <property name="label" translatable="yes">Show "Confirm Exit" Dialog</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="_hideCursorBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">Hide Cursor:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkRadioButton" id="_hideCursorNever">
+                                        <property name="label" translatable="yes">Never</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">False</property>
+                                        <property name="halign">start</property>
+                                        <property name="margin-top">5</property>
+                                        <property name="margin-bottom">5</property>
+                                        <property name="active">True</property>
+                                        <property name="draw-indicator">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkRadioButton" id="_hideCursorOnIdle">
+                                        <property name="label" translatable="yes">On Idle</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">False</property>
+                                        <property name="halign">start</property>
+                                        <property name="margin-top">5</property>
+                                        <property name="margin-bottom">5</property>
+                                        <property name="draw-indicator">True</property>
+                                        <property name="group">_hideCursorNever</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkRadioButton" id="_hideCursorAlways">
+                                        <property name="label" translatable="yes">Always</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">False</property>
+                                        <property name="halign">start</property>
+                                        <property name="margin-top">5</property>
+                                        <property name="margin-bottom">5</property>
+                                        <property name="draw-indicator">True</property>
+                                        <property name="group">_hideCursorNever</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">5</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatGameDir">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Game Directories</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkScrolledWindow">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="margin-bottom">10</property>
+                                    <property name="shadow-type">in</property>
+                                    <child>
+                                      <object class="GtkTreeView" id="_gameDirsBox">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="headers-visible">False</property>
+                                        <property name="headers-clickable">False</property>
+                                        <child internal-child="selection">
+                                          <object class="GtkTreeSelection"/>
+                                        </child>
+                                      </object>
+                                    </child>
+                                    <style>
+                                      <class name="GameDir"/>
+                                    </style>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkEntry" id="_addGameDirBox">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Enter a game directory to add to the list</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkToggleButton" id="_addDir">
+                                        <property name="label" translatable="yes">Add</property>
+                                        <property name="width-request">80</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">True</property>
+                                        <property name="tooltip-text" translatable="yes"> Add a game directory to the list</property>
+                                        <property name="margin-left">5</property>
+                                        <signal name="toggled" handler="AddDir_Pressed" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkToggleButton" id="_removeDir">
+                                        <property name="label" translatable="yes">Remove</property>
+                                        <property name="width-request">80</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">True</property>
+                                        <property name="tooltip-text" translatable="yes">Remove selected game directory</property>
+                                        <property name="margin-left">5</property>
+                                        <signal name="toggled" handler="RemoveDir_Pressed" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatThemes">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Themes</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="_custThemeToggle">
+                                    <property name="label" translatable="yes">Use Custom Theme</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Enable or disable custom themes in the GUI</property>
+                                    <property name="halign">start</property>
+                                    <property name="draw-indicator">True</property>
+                                    <signal name="toggled" handler="CustThemeToggle_Activated" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel" id="_custThemePathLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Path to custom GUI theme</property>
+                                        <property name="label" translatable="yes">Custom Theme Path:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkEntry" id="_custThemePath">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Path to custom GUI theme</property>
+                                        <property name="valign">center</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkToggleButton" id="_browseThemePath">
+                                        <property name="label" translatable="yes">Browse...</property>
+                                        <property name="width-request">80</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">True</property>
+                                        <property name="tooltip-text" translatable="yes">Browse for a custom GUI theme</property>
+                                        <property name="margin-left">5</property>
+                                        <signal name="toggled" handler="BrowseThemeDir_Pressed" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">10</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">6</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">General</property>
+                      </object>
+                      <packing>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="TabInput">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">10</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-top">5</property>
+                            <property name="margin-bottom">5</property>
+                            <child>
+                              <object class="GtkCheckButton" id="_dockedModeToggle">
+                                <property name="label" translatable="yes">Enable Docked Mode</property>
+                                <property name="visible">True</property>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">False</property>
+                                <property name="tooltip-text" translatable="yes">Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.&#13;Configure player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.&#13;Leave ON if unsure.</property>
+                                <property name="draw-indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="padding">10</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="_directKeyboardAccess">
+                                <property name="label" translatable="yes">Direct Keyboard Access</property>
+                                <property name="visible">True</property>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">False</property>
+                                <property name="tooltip-text" translatable="yes">Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.</property>
+                                <property name="draw-indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="padding">10</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="_directMouseAccess">
+                                <property name="label" translatable="yes">Direct Mouse Access</property>
+                                <property name="visible">True</property>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">False</property>
+                                <property name="tooltip-text" translatable="yes">Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.</property>
+                                <property name="draw-indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="padding">10</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <!-- n-columns=5 n-rows=5 -->
+                          <object class="GtkGrid" id="ControllerGrid">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <property name="column-spacing">20</property>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 1</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController1">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">0</property>
+                                <property name="top-attach">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 3</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController3">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">4</property>
+                                <property name="top-attach">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 2</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController2">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">2</property>
+                                <property name="top-attach">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Handheld</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureControllerH">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">4</property>
+                                <property name="top-attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 6</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController6">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">4</property>
+                                <property name="top-attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 5</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController5">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">2</property>
+                                <property name="top-attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 7</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController7">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">0</property>
+                                <property name="top-attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 4</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController4">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">0</property>
+                                <property name="top-attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                    <property name="label" translatable="yes">Player 8</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkToggleButton" id="_configureController8">
+                                    <property name="label" translatable="yes">Configure</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="margin-left">20</property>
+                                    <property name="margin-right">20</property>
+                                    <property name="margin-top">20</property>
+                                    <property name="margin-bottom">20</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left-attach">2</property>
+                                <property name="top-attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">1</property>
+                                <property name="top-attach">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">3</property>
+                                <property name="top-attach">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">3</property>
+                                <property name="top-attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">3</property>
+                                <property name="top-attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">1</property>
+                                <property name="top-attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">1</property>
+                                <property name="top-attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">1</property>
+                                <property name="top-attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">1</property>
+                                <property name="top-attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">3</property>
+                                <property name="top-attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">3</property>
+                                <property name="top-attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">0</property>
+                                <property name="top-attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">2</property>
+                                <property name="top-attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">4</property>
+                                <property name="top-attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">0</property>
+                                <property name="top-attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">2</property>
+                                <property name="top-attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSeparator">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="left-attach">4</property>
+                                <property name="top-attach">3</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Input</property>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="TabSystem">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">10</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox" id="CatCore">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="valign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Core</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox" id="RegionBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System Region</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">System Region:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_systemRegionSelect">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System Region</property>
+                                        <property name="margin-left">5</property>
+                                        <items>
+                                          <item id="Japan" translatable="yes">Japan</item>
+                                          <item id="USA" translatable="yes">USA</item>
+                                          <item id="Europe" translatable="yes">Europe</item>
+                                          <item id="Australia" translatable="yes">Australia</item>
+                                          <item id="China" translatable="yes">China</item>
+                                          <item id="Korea" translatable="yes">Korea</item>
+                                          <item id="Taiwan" translatable="yes">Taiwan</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="LanguageBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System Language</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">System Language:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_systemLanguageSelect">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System Language</property>
+                                        <items>
+                                          <item id="AmericanEnglish" translatable="yes">American English</item>
+                                          <item id="BritishEnglish" translatable="yes">British English</item>
+                                          <item id="CanadianFrench" translatable="yes">Canadian French</item>
+                                          <item id="Chinese" translatable="yes">Chinese</item>
+                                          <item id="Dutch" translatable="yes">Dutch</item>
+                                          <item id="French" translatable="yes">French</item>
+                                          <item id="German" translatable="yes">German</item>
+                                          <item id="Italian" translatable="yes">Italian</item>
+                                          <item id="Japanese" translatable="yes">Japanese</item>
+                                          <item id="Korean" translatable="yes">Korean</item>
+                                          <item id="LatinAmericanSpanish" translatable="yes">Latin American Spanish</item>
+                                          <item id="Portuguese" translatable="yes">Portuguese</item>
+                                          <item id="Russian" translatable="yes">Russian</item>
+                                          <item id="SimplifiedChinese" translatable="yes">Simplified Chinese</item>
+                                          <item id="Spanish" translatable="yes">Spanish</item>
+                                          <item id="Taiwanese" translatable="yes">Taiwanese</item>
+                                          <item id="TraditionalChinese" translatable="yes">Traditional Chinese</item>
+                                          <item id="BrazilianPortuguese" translatable="yes">Brazilian Portuguese</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="TimeZoneBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System TimeZone</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">System TimeZone:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkEntry" id="_systemTimeZoneEntry">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Change System TimeZone</property>
+                                        <property name="margin-left">5</property>
+                                        <property name="completion">_systemTimeZoneCompletion</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox" id="TimeBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change System Time</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">System Time:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="_systemTimeYearSpin">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="text" translatable="yes">2000</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="adjustment">_systemTimeYearSpinAdjustment</property>
+                                        <property name="wrap">True</property>
+                                        <property name="value">2000</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="halign">end</property>
+                                        <property name="label">-</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="_systemTimeMonthSpin">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="text" translatable="yes">1</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="adjustment">_systemTimeMonthSpinAdjustment</property>
+                                        <property name="wrap">True</property>
+                                        <property name="value">1</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="halign">end</property>
+                                        <property name="label">-</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="_systemTimeDaySpin">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="text" translatable="yes">1</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="adjustment">_systemTimeDaySpinAdjustment</property>
+                                        <property name="wrap">True</property>
+                                        <property name="value">1</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">5</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="_systemTimeHourSpin">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="text" translatable="yes">0</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="adjustment">_systemTimeHourSpinAdjustment</property>
+                                        <property name="wrap">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">6</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="halign">end</property>
+                                        <property name="label">:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">7</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="_systemTimeMinuteSpin">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="text" translatable="yes">0</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="adjustment">_systemTimeMinuteSpinAdjustment</property>
+                                        <property name="wrap">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">8</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_vSyncToggle">
+                                    <property name="label" translatable="yes">Enable VSync</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.&#13;Can be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.&#13;Leave ON if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_ptcToggle">
+                                    <property name="label" translatable="yes">Enable PPTC (Profiled Persistent Translation Cache)</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Saves translated JIT functions so that they do not need to be translated every time the game loads.&#13;Reduces stuttering and significantly speeds up boot times after the first boot of a game.&#13;Leave ON if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">6</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_internetToggle">
+                                    <property name="label" translatable="yes">Enable Guest Internet Access</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Allows the emulated application to connect to the Internet.&#13;Games with a LAN mode can connect to each other when this is enabled and the systems are connected to the same access point. This includes real consoles as well.&#13;Does NOT allow connecting to Nintendo servers. May cause crashing in certain games that try to connect to the Internet.&#13;Leave OFF if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">7</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_fsicToggle">
+                                    <property name="label" translatable="yes">Enable FS Integrity Checks</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.&#13;Has no impact on performance and is meant to help troubleshooting.&#13;Leave ON if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">8</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="_audioBackendBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="tooltip-text" translatable="yes">Changes the backend used to render audio.&#13;SDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.&#13;Set to SDL2 if unsure.</property>
+                                    <property name="halign">end</property>
+                                    <property name="margin-right">5</property>
+                                    <property name="label" translatable="yes">Audio Backend: </property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="padding">5</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="_memoryManagerBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="tooltip-text" translatable="yes">Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.&#13;Set to HOST UNCHECKED if unsure.</property>
+                                    <property name="halign">end</property>
+                                    <property name="margin-right">5</property>
+                                    <property name="label" translatable="yes">Memory Manager Mode: </property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkRadioButton" id="_mmSoftware">
+                                    <property name="label" translatable="yes">Software</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Use a software page table for address translation. Highest accuracy but slowest performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkRadioButton" id="_mmHost">
+                                    <property name="label" translatable="yes">Host (fast)</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Directly map memory in the host address space. Much faster JIT compilation and execution.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                    <property name="group">_mmSoftware</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkRadioButton" id="_mmHostUnsafe">
+                                    <property name="label" translatable="yes">Host Unchecked (fastest, unsafe)</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                    <property name="group">_mmSoftware</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">5</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="padding">5</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatHacks">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="valign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="label" translatable="yes">Hacks</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="label" translatable="yes"> (may cause instability)</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="_expandRamToggle">
+                                    <property name="label" translatable="yes">Use alternative memory layout (Developers)</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Utilizes an alternative MemoryMode layout to mimic a Switch development model.&#13;This is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.&#13;Leave OFF if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_ignoreToggle">
+                                    <property name="label" translatable="yes">Ignore Missing Services</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.&#13;Leave OFF if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">4</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">System</property>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="TabGraphics">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox" id="CatFeatures">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-left">5</property>
+                                <property name="margin-right">5</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Features</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="FeaturesOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Executes graphics backend commands on a second thread.&#13;Speeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.&#13;Set to AUTO if unsure.</property>
+                                        <property name="label" translatable="yes">Graphics Backend Multithreading:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_galThreading">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Executes graphics backend commands on a second thread.&#13;Speeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.&#13;Set to AUTO if unsure.</property>
+                                        <property name="active-id">-1</property>
+                                        <items>
+                                          <item id="Auto" translatable="yes">Auto</item>
+                                          <item id="Off" translatable="yes">Off</item>
+                                          <item id="On" translatable="yes">On</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Graphics Backend to use</property>
+                                        <property name="label" translatable="yes">Graphics Backend:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_graphicsBackend">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Graphics Backend to use</property>
+                                        <property name="active-id">-1</property>
+                                        <items>
+                                          <item id="0" translatable="yes">Vulkan</item>
+                                          <item id="1" translatable="yes">OpenGL</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
+                                        <property name="label" translatable="yes">Preferred GPU:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_preferredGpu">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
+                                        <property name="active-id">-1</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatEnhancements">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-left">5</property>
+                                <property name="margin-right">5</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Enhancements</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="EnhancementOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="_shaderCacheToggle">
+                                    <property name="label" translatable="yes">Enable Shader Cache</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Saves a disk shader cache which reduces stuttering in subsequent runs.&#13;Leave ON if unsure.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_textureRecompressionToggle">
+                                    <property name="label" translatable="yes">Enable Texture Recompression</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Enables or disables Texture Recompression. Reduces VRAM usage at the cost of texture quality, and may also increase stuttering</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_macroHLEToggle">
+                                    <property name="label" translatable="yes">Enable Macro HLE</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Enables or disables high-level emulation of Macro code. Improves performance but may cause graphical glitches in some games</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Resolution Scale applied to applicable render targets.</property>
+                                        <property name="label" translatable="yes">Resolution Scale:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_resScaleCombo">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Resolution Scale applied to applicable render targets.</property>
+                                        <property name="active-id">1</property>
+                                        <items>
+                                          <item id="1" translatable="yes">Native (720p/1080p)</item>
+                                          <item id="2" translatable="yes">2x (1440p/2160p)</item>
+                                          <item id="3" translatable="yes">3x (2160p/3240p)</item>
+                                          <item id="4" translatable="yes">4x (2880p/4320p)</item>
+                                          <item id="-1" translatable="yes">Custom (not recommended)</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkEntry" id="_resScaleText">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.</property>
+                                        <property name="valign">center</property>
+                                        <property name="caps-lock-warning">False</property>
+                                        <property name="placeholder-text">1.0</property>
+                                        <property name="input-purpose">number</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Applies a final effect to the game render</property>
+                                        <property name="label" translatable="yes">Post Processing Effect:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_antiAliasing">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Applies anti-aliasing to the game render</property>
+                                        <property name="active-id">1</property>
+                                        <items>
+                                          <item id="0" translatable="yes">None</item>
+                                          <item id="1" translatable="yes">FXAA</item>
+                                          <item id="2" translatable="yes">SMAA Low</item>
+                                          <item id="3" translatable="yes">SMAA Medium</item>
+                                          <item id="4" translatable="yes">SMAA High</item>
+                                          <item id="5" translatable="yes">SMAA Ultra</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="width-request">100</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Enables Framebuffer Upscaling</property>
+                                        <property name="label" translatable="yes">Upscale: </property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_scalingFilter">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Enables Framebuffer Upscaling</property>
+                                        <property name="active-id">1</property>
+                                        <items>
+                                          <item id="0" translatable="yes">Bilinear</item>
+                                          <item id="1" translatable="yes">Nearest</item>
+                                          <item id="2" translatable="yes">FSR</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkScale" id="_scalingFilterSlider">
+                                        <property name="width-request">200</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="margin-start">5</property>
+                                        <property name="adjustment">_scalingFilterLevel</property>
+                                        <property name="round-digits">1</property>
+                                        <property name="value-pos">right</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">5</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Level of Anisotropic Filtering (set to Auto to use the value requested by the game)</property>
+                                        <property name="label" translatable="yes">Anisotropic Filtering:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_anisotropy">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Level of Anisotropic Filtering (set to Auto to use the value requested by the game)</property>
+                                        <property name="active-id">-1</property>
+                                        <items>
+                                          <item id="-1" translatable="yes">Auto</item>
+                                          <item id="2" translatable="yes">2x</item>
+                                          <item id="4" translatable="yes">4x</item>
+                                          <item id="8" translatable="yes">8x</item>
+                                          <item id="16" translatable="yes">16x</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">6</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Aspect Ratio applied to the renderer window.</property>
+                                        <property name="label" translatable="yes">Aspect Ratio:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_aspectRatio">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Aspect Ratio applied to the renderer window.</property>
+                                        <property name="active-id">1</property>
+                                        <items>
+                                          <item id="0" translatable="yes">4:3</item>
+                                          <item id="1" translatable="yes">16:9</item>
+                                          <item id="2" translatable="yes">16:10</item>
+                                          <item id="3" translatable="yes">21:9</item>
+                                          <item id="4" translatable="yes">32:9</item>
+                                          <item id="5" translatable="yes">Stretch to Fit Window</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">7</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatDev">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-left">5</property>
+                                <property name="margin-right">5</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Developer Options</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="DevOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Graphics Shaders Dump Path</property>
+                                        <property name="label" translatable="yes">Graphics Shaders Dump Path:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkEntry" id="_graphicsShadersDumpPath">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Graphics Shaders Dump Path</property>
+                                        <property name="valign">center</property>
+                                        <property name="caps-lock-warning">False</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">4</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Graphics</property>
+                      </object>
+                      <packing>
+                        <property name="position">3</property>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="TabLogging">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">10</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox" id="CatLogging">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Logging</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="LogggingOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="valign">start</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="_fileLogToggle">
+                                    <property name="label" translatable="yes">Enable Logging to File</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Saves console logging to a log file on disk. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_stubLogToggle">
+                                    <property name="label" translatable="yes">Enable Stub Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints stub log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_infoLogToggle">
+                                    <property name="label" translatable="yes">Enable Info Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints info log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">4</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_warningLogToggle">
+                                    <property name="label" translatable="yes">Enable Warning Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints warning log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">5</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_errorLogToggle">
+                                    <property name="label" translatable="yes">Enable Error Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints error log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">6</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_guestLogToggle">
+                                    <property name="label" translatable="yes">Enable Guest Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints guest log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">7</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_fsAccessLogToggle">
+                                    <property name="label" translatable="yes">Enable Fs Access Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">8</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
+                                        <property name="label" translatable="yes">Fs Global Access Log Mode:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
+                                        <property name="text" translatable="yes">0</property>
+                                        <property name="adjustment">_fsLogSpinAdjustment</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">9</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatDevLogging">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="margin-top">10</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="tooltip-text" translatable="yes">Use with care</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Developer Options (WARNING: Will reduce performance)</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="DevLoggingOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="valign">start</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin-top">5</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Requires appropriate log levels enabled.</property>
+                                        <property name="label" translatable="yes">Graphics Backend Log Level</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">22</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_graphicsDebugLevel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Requires appropriate log levels enabled.</property>
+                                        <property name="margin-left">5</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">22</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_debugLogToggle">
+                                    <property name="label" translatable="yes">Enable Debug Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints debug log messages in the console.&#13;Only use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">21</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="_traceLogToggle">
+                                    <property name="label" translatable="yes">Enable Trace Logs</property>
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">False</property>
+                                    <property name="tooltip-text" translatable="yes">Prints trace log messages in the console. Does not affect performance.</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-top">5</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="draw-indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">22</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">22</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Logging</property>
+                      </object>
+                      <packing>
+                        <property name="position">4</property>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="TabMultiplayer">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-left">5</property>
+                        <property name="margin-right">10</property>
+                        <property name="margin-top">5</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkBox" id="CatMultiplayer">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="valign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">Multiplayer</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="MultiplayerOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="valign">start</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox" id="ModeBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change Multiplayer Mode</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">Mode:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_multiModeSelect">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">Change Multiplayer Mode</property>
+                                        <property name="active-id">Disabled</property>
+                                        <items>
+                                          <item id="Disabled" translatable="yes">Disabled</item>
+                                          <item id="LdnMitm" translatable="yes">ldn_mitm</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">3</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="CatLAN">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="valign">start</property>
+                            <property name="margin-left">5</property>
+                            <property name="margin-right">5</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="margin-bottom">5</property>
+                                <property name="label" translatable="yes">LAN Mode</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="LANOptions">
+                                <property name="visible">True</property>
+                                <property name="can-focus">False</property>
+                                <property name="valign">start</property>
+                                <property name="margin-left">10</property>
+                                <property name="margin-right">10</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkBox" id="NetworkInterfaceBox">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">The network interface used for LAN/LDN features</property>
+                                        <property name="halign">end</property>
+                                        <property name="label" translatable="yes">Network Interface:</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkComboBoxText" id="_multiLanSelect">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">False</property>
+                                        <property name="tooltip-text" translatable="yes">The network interface used for LAN/LDN features</property>
+                                        <property name="active-id">0</property>
+                                        <items>
+                                          <item id="0" translatable="yes">Default</item>
+                                        </items>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="margin-bottom">5</property>
+                                    <property name="label" translatable="yes">To use LAN functionality in games, Enable Guest Internet Access must be checked in System.</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="padding">5</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">5</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="label" translatable="yes">Multiplayer</property>
+                      </object>
+                      <packing>
+                        <property name="position">5</property>
+                        <property name="tab-fill">False</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButtonBox" id="_buttonBox">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-right">5</property>
+            <property name="margin-top">3</property>
+            <property name="margin-bottom">3</property>
+            <property name="spacing">5</property>
+            <property name="layout-style">end</property>
+            <child>
+              <object class="GtkToggleButton" id="SaveToggle">
+                <property name="label" translatable="yes">Save</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToggleButton" id="CloseToggle">
+                <property name="label" translatable="yes">Close</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Apply</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <signal name="clicked" handler="ApplyToggle_Activated" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Windows/TitleUpdateWindow.cs b/src/Ryujinx/UI/Windows/TitleUpdateWindow.cs
new file mode 100644
index 00000000..1df92933
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/TitleUpdateWindow.cs
@@ -0,0 +1,206 @@
+using Gtk;
+using LibHac.Common;
+using LibHac.Fs;
+using LibHac.Fs.Fsa;
+using LibHac.FsSystem;
+using LibHac.Ns;
+using LibHac.Tools.FsSystem;
+using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Utilities;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Widgets;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using GUI = Gtk.Builder.ObjectAttribute;
+using SpanHelpers = LibHac.Common.SpanHelpers;
+
+namespace Ryujinx.UI.Windows
+{
+    public class TitleUpdateWindow : Window
+    {
+        private readonly MainWindow _parent;
+        private readonly VirtualFileSystem _virtualFileSystem;
+        private readonly string _titleId;
+        private readonly string _updateJsonPath;
+
+        private TitleUpdateMetadata _titleUpdateWindowData;
+
+        private readonly Dictionary<RadioButton, string> _radioButtonToPathDictionary;
+        private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
+        [GUI] Label _baseTitleInfoLabel;
+        [GUI] Box _availableUpdatesBox;
+        [GUI] RadioButton _noUpdateRadioButton;
+#pragma warning restore CS0649, IDE0044
+
+        public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.UI.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, titleId, titleName) { }
+
+        private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
+        {
+            _parent = parent;
+
+            builder.Autoconnect(this);
+
+            _titleId = titleId;
+            _virtualFileSystem = virtualFileSystem;
+            _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json");
+            _radioButtonToPathDictionary = new Dictionary<RadioButton, string>();
+
+            try
+            {
+                _titleUpdateWindowData = JsonHelper.DeserializeFromFile(_updateJsonPath, _serializerContext.TitleUpdateMetadata);
+            }
+            catch
+            {
+                _titleUpdateWindowData = new TitleUpdateMetadata
+                {
+                    Selected = "",
+                    Paths = new List<string>(),
+                };
+            }
+
+            _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]";
+
+            foreach (string path in _titleUpdateWindowData.Paths)
+            {
+                AddUpdate(path);
+            }
+
+            if (_titleUpdateWindowData.Selected == "")
+            {
+                _noUpdateRadioButton.Active = true;
+            }
+            else
+            {
+                foreach ((RadioButton update, var _) in _radioButtonToPathDictionary.Where(keyValuePair => keyValuePair.Value == _titleUpdateWindowData.Selected))
+                {
+                    update.Active = true;
+                }
+            }
+        }
+
+        private void AddUpdate(string path)
+        {
+            if (File.Exists(path))
+            {
+                using FileStream file = new(path, FileMode.Open, FileAccess.Read);
+
+                PartitionFileSystem nsp = new();
+                nsp.Initialize(file.AsStorage()).ThrowIfFailure();
+
+                try
+                {
+                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);
+
+                    if (controlNca != null && patchNca != null)
+                    {
+                        ApplicationControlProperty controlData = new();
+
+                        using var nacpFile = new UniqueRef<IFile>();
+
+                        controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
+                        nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
+
+                        RadioButton radioButton = new($"Version {controlData.DisplayVersionString.ToString()} - {path}");
+                        radioButton.JoinGroup(_noUpdateRadioButton);
+
+                        _availableUpdatesBox.Add(radioButton);
+                        _radioButtonToPathDictionary.Add(radioButton, path);
+
+                        radioButton.Show();
+                        radioButton.Active = true;
+                    }
+                    else
+                    {
+                        GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
+                    }
+                }
+                catch (Exception exception)
+                {
+                    GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
+                }
+            }
+        }
+
+        private void RemoveUpdates(bool removeSelectedOnly = false)
+        {
+            foreach (RadioButton radioButton in _noUpdateRadioButton.Group)
+            {
+                if (radioButton.Label != "No Update" && (!removeSelectedOnly || radioButton.Active))
+                {
+                    _availableUpdatesBox.Remove(radioButton);
+                    _radioButtonToPathDictionary.Remove(radioButton);
+                    radioButton.Dispose();
+                }
+            }
+        }
+
+        private void AddButton_Clicked(object sender, EventArgs args)
+        {
+            using FileChooserNative fileChooser = new("Select update files", this, FileChooserAction.Open, "Add", "Cancel");
+
+            fileChooser.SelectMultiple = true;
+
+            FileFilter filter = new()
+            {
+                Name = "Switch Game Updates",
+            };
+            filter.AddPattern("*.nsp");
+
+            fileChooser.AddFilter(filter);
+
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                foreach (string path in fileChooser.Filenames)
+                {
+                    AddUpdate(path);
+                }
+            }
+        }
+
+        private void RemoveButton_Clicked(object sender, EventArgs args)
+        {
+            RemoveUpdates(true);
+        }
+
+        private void RemoveAllButton_Clicked(object sender, EventArgs args)
+        {
+            RemoveUpdates();
+        }
+
+        private void SaveButton_Clicked(object sender, EventArgs args)
+        {
+            _titleUpdateWindowData.Paths.Clear();
+            _titleUpdateWindowData.Selected = "";
+
+            foreach (string paths in _radioButtonToPathDictionary.Values)
+            {
+                _titleUpdateWindowData.Paths.Add(paths);
+            }
+
+            foreach (RadioButton radioButton in _noUpdateRadioButton.Group)
+            {
+                if (radioButton.Active)
+                {
+                    _titleUpdateWindowData.Selected = _radioButtonToPathDictionary.TryGetValue(radioButton, out string updatePath) ? updatePath : "";
+                }
+            }
+
+            JsonHelper.SerializeToFile(_updateJsonPath, _titleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
+
+            _parent.UpdateGameTable();
+
+            Dispose();
+        }
+
+        private void CancelButton_Clicked(object sender, EventArgs args)
+        {
+            Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/TitleUpdateWindow.glade b/src/Ryujinx/UI/Windows/TitleUpdateWindow.glade
new file mode 100644
index 00000000..cfbac86d
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/TitleUpdateWindow.glade
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkWindow" id="_titleUpdateWindow">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Ryujinx - Title Update Manager</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="default_width">550</property>
+    <property name="default_height">250</property>
+    <child>
+      <object class="GtkBox" id="MainBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkBox" id="UpdatesBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel" id="_baseTitleInfoLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="label" translatable="yes">Available Updates</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="margin_left">10</property>
+                <property name="margin_right">10</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="_availableUpdatesBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkRadioButton" id="_noUpdateRadioButton">
+                            <property name="label" translatable="yes">No Update</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="active">True</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="layout_style">start</property>
+                <child>
+                  <object class="GtkButton" id="_addUpdate">
+                    <property name="label" translatable="yes">Add</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Adds an update to this list</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="AddButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_removeUpdate">
+                    <property name="label" translatable="yes">Remove</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Removes the selected update</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="RemoveButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_removeAllButton">
+                    <property name="label" translatable="yes">Remove All</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Removes all the updates</property>
+                    <property name="margin_left">10</property>
+                    <signal name="clicked" handler="RemoveAllButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">10</property>
+                <property name="margin_bottom">10</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <object class="GtkButton" id="_saveButton">
+                    <property name="label" translatable="yes">Save</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="_cancelButton">
+                    <property name="label" translatable="yes">Cancel</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">10</property>
+                    <property name="margin_top">2</property>
+                    <property name="margin_bottom">2</property>
+                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+  </object>
+</interface>
diff --git a/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.Designer.cs b/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.Designer.cs
new file mode 100644
index 00000000..bc5a18f9
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.Designer.cs
@@ -0,0 +1,255 @@
+using Gtk;
+using Pango;
+using System;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class UserProfilesManagerWindow : Window
+    {
+        private Box _mainBox;
+        private Label _selectedLabel;
+        private Box _selectedUserBox;
+        private Image _selectedUserImage;
+        private Box _selectedUserInfoBox;
+        private Entry _selectedUserNameEntry;
+        private Label _selectedUserIdLabel;
+        private Box _selectedUserButtonsBox;
+        private Button _saveProfileNameButton;
+        private Button _changeProfileImageButton;
+        private Box _usersTreeViewBox;
+        private Label _availableUsersLabel;
+        private ScrolledWindow _usersTreeViewWindow;
+        private ListStore _tableStore;
+        private TreeView _usersTreeView;
+        private Box _bottomBox;
+        private Button _addButton;
+        private Button _deleteButton;
+        private Button _closeButton;
+
+        private void InitializeComponent()
+        {
+            //
+            // UserProfilesManagerWindow
+            //
+            CanFocus = false;
+            Resizable = false;
+            Modal = true;
+            WindowPosition = WindowPosition.Center;
+            DefaultWidth = 620;
+            DefaultHeight = 548;
+            TypeHint = Gdk.WindowTypeHint.Dialog;
+
+            //
+            // _mainBox
+            //
+            _mainBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _selectedLabel
+            //
+            _selectedLabel = new Label("Selected User Profile:")
+            {
+                Margin = 15,
+                Attributes = new AttrList(),
+                Halign = Align.Start,
+            };
+            _selectedLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
+
+            //
+            // _viewBox
+            //
+            _usersTreeViewBox = new Box(Orientation.Vertical, 0);
+
+            //
+            // _SelectedUserBox
+            //
+            _selectedUserBox = new Box(Orientation.Horizontal, 0)
+            {
+                MarginStart = 30,
+            };
+
+            //
+            // _selectedUserImage
+            //
+            _selectedUserImage = new Image();
+
+            //
+            // _selectedUserInfoBox
+            //
+            _selectedUserInfoBox = new Box(Orientation.Vertical, 0)
+            {
+                Homogeneous = true,
+            };
+
+            //
+            // _selectedUserNameEntry
+            //
+            _selectedUserNameEntry = new Entry("")
+            {
+                MarginStart = 15,
+                MaxLength = (int)MaxProfileNameLength,
+            };
+            _selectedUserNameEntry.KeyReleaseEvent += SelectedUserNameEntry_KeyReleaseEvent;
+
+            //
+            // _selectedUserIdLabel
+            //
+            _selectedUserIdLabel = new Label("")
+            {
+                MarginTop = 15,
+                MarginStart = 15,
+            };
+
+            //
+            // _selectedUserButtonsBox
+            //
+            _selectedUserButtonsBox = new Box(Orientation.Vertical, 0)
+            {
+                MarginEnd = 30,
+            };
+
+            //
+            // _saveProfileNameButton
+            //
+            _saveProfileNameButton = new Button()
+            {
+                Label = "Save Profile Name",
+                CanFocus = true,
+                ReceivesDefault = true,
+                Sensitive = false,
+            };
+            _saveProfileNameButton.Clicked += EditProfileNameButton_Pressed;
+
+            //
+            // _changeProfileImageButton
+            //
+            _changeProfileImageButton = new Button()
+            {
+                Label = "Change Profile Image",
+                CanFocus = true,
+                ReceivesDefault = true,
+                MarginTop = 10,
+            };
+            _changeProfileImageButton.Clicked += ChangeProfileImageButton_Pressed;
+
+            //
+            // _availableUsersLabel
+            //
+            _availableUsersLabel = new Label("Available User Profiles:")
+            {
+                Margin = 15,
+                Attributes = new AttrList(),
+                Halign = Align.Start,
+            };
+            _availableUsersLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
+
+            //
+            // _usersTreeViewWindow
+            //
+            _usersTreeViewWindow = new ScrolledWindow()
+            {
+                ShadowType = ShadowType.In,
+                CanFocus = true,
+                Expand = true,
+                MarginStart = 30,
+                MarginEnd = 30,
+                MarginBottom = 15,
+            };
+
+            //
+            // _tableStore
+            //
+            _tableStore = new ListStore(typeof(bool), typeof(Gdk.Pixbuf), typeof(string), typeof(Gdk.RGBA));
+
+            //
+            // _usersTreeView
+            //
+            _usersTreeView = new TreeView(_tableStore)
+            {
+                HoverSelection = true,
+                HeadersVisible = false,
+            };
+            _usersTreeView.RowActivated += UsersTreeView_Activated;
+
+            //
+            // _bottomBox
+            //
+            _bottomBox = new Box(Orientation.Horizontal, 0)
+            {
+                MarginStart = 30,
+                MarginEnd = 30,
+                MarginBottom = 15,
+            };
+
+            //
+            // _addButton
+            //
+            _addButton = new Button()
+            {
+                Label = "Add New Profile",
+                CanFocus = true,
+                ReceivesDefault = true,
+                HeightRequest = 35,
+            };
+            _addButton.Clicked += AddButton_Pressed;
+
+            //
+            // _deleteButton
+            //
+            _deleteButton = new Button()
+            {
+                Label = "Delete Selected Profile",
+                CanFocus = true,
+                ReceivesDefault = true,
+                HeightRequest = 35,
+                MarginStart = 10,
+            };
+            _deleteButton.Clicked += DeleteButton_Pressed;
+
+            //
+            // _closeButton
+            //
+            _closeButton = new Button()
+            {
+                Label = "Close",
+                CanFocus = true,
+                ReceivesDefault = true,
+                HeightRequest = 35,
+                WidthRequest = 80,
+            };
+            _closeButton.Clicked += CloseButton_Pressed;
+
+            ShowComponent();
+        }
+
+        private void ShowComponent()
+        {
+            _usersTreeViewWindow.Add(_usersTreeView);
+
+            _usersTreeViewBox.Add(_usersTreeViewWindow);
+            _bottomBox.PackStart(_addButton, false, false, 0);
+            _bottomBox.PackStart(_deleteButton, false, false, 0);
+            _bottomBox.PackEnd(_closeButton, false, false, 0);
+
+            _selectedUserInfoBox.Add(_selectedUserNameEntry);
+            _selectedUserInfoBox.Add(_selectedUserIdLabel);
+
+            _selectedUserButtonsBox.Add(_saveProfileNameButton);
+            _selectedUserButtonsBox.Add(_changeProfileImageButton);
+
+            _selectedUserBox.Add(_selectedUserImage);
+            _selectedUserBox.PackStart(_selectedUserInfoBox, false, false, 0);
+            _selectedUserBox.PackEnd(_selectedUserButtonsBox, false, false, 0);
+
+            _mainBox.PackStart(_selectedLabel, false, false, 0);
+            _mainBox.PackStart(_selectedUserBox, false, true, 0);
+            _mainBox.PackStart(_availableUsersLabel, false, false, 0);
+            _mainBox.Add(_usersTreeViewBox);
+            _mainBox.Add(_bottomBox);
+
+            Add(_mainBox);
+
+            ShowAll();
+        }
+    }
+}
diff --git a/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.cs b/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.cs
new file mode 100644
index 00000000..d1e5fa9f
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/UserProfilesManagerWindow.cs
@@ -0,0 +1,328 @@
+using Gtk;
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.HOS.Services.Account.Acc;
+using Ryujinx.UI.Common.Configuration;
+using Ryujinx.UI.Widgets;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Image = SixLabors.ImageSharp.Image;
+
+namespace Ryujinx.UI.Windows
+{
+    public partial class UserProfilesManagerWindow : Window
+    {
+        private const uint MaxProfileNameLength = 0x20;
+
+        private readonly AccountManager _accountManager;
+        private readonly ContentManager _contentManager;
+
+        private byte[] _bufferImageProfile;
+        private string _tempNewProfileName;
+
+        private Gdk.RGBA _selectedColor;
+
+        private readonly ManualResetEvent _avatarsPreloadingEvent = new(false);
+
+        public UserProfilesManagerWindow(AccountManager accountManager, ContentManager contentManager, VirtualFileSystem virtualFileSystem) : base($"Ryujinx {Program.Version} - Manage User Profiles")
+        {
+            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
+
+            InitializeComponent();
+
+            _selectedColor.Red = 0.212;
+            _selectedColor.Green = 0.843;
+            _selectedColor.Blue = 0.718;
+            _selectedColor.Alpha = 1;
+
+            _accountManager = accountManager;
+            _contentManager = contentManager;
+
+            CellRendererToggle userSelectedToggle = new();
+            userSelectedToggle.Toggled += UserSelectedToggle_Toggled;
+
+            // NOTE: Uncomment following line when multiple selection of user profiles is supported.
+            //_usersTreeView.AppendColumn("Selected",  userSelectedToggle,       "active", 0);
+            _usersTreeView.AppendColumn("User Icon", new CellRendererPixbuf(), "pixbuf", 1);
+            _usersTreeView.AppendColumn("User Info", new CellRendererText(), "text", 2, "background-rgba", 3);
+
+            _tableStore.SetSortColumnId(0, SortType.Descending);
+
+            RefreshList();
+
+            if (_contentManager.GetCurrentFirmwareVersion() != null)
+            {
+                Task.Run(() =>
+                {
+                    AvatarWindow.PreloadAvatars(contentManager, virtualFileSystem);
+                    _avatarsPreloadingEvent.Set();
+                });
+            }
+        }
+
+        public void RefreshList()
+        {
+            _tableStore.Clear();
+
+            foreach (UserProfile userProfile in _accountManager.GetAllUsers())
+            {
+                _tableStore.AppendValues(userProfile.AccountState == AccountState.Open, new Gdk.Pixbuf(userProfile.Image, 96, 96), $"{userProfile.Name}\n{userProfile.UserId}", Gdk.RGBA.Zero);
+
+                if (userProfile.AccountState == AccountState.Open)
+                {
+                    _selectedUserImage.Pixbuf = new Gdk.Pixbuf(userProfile.Image, 96, 96);
+                    _selectedUserIdLabel.Text = userProfile.UserId.ToString();
+                    _selectedUserNameEntry.Text = userProfile.Name;
+
+                    _deleteButton.Sensitive = userProfile.UserId != AccountManager.DefaultUserId;
+
+                    _usersTreeView.Model.GetIterFirst(out TreeIter firstIter);
+                    _tableStore.SetValue(firstIter, 3, _selectedColor);
+                }
+            }
+        }
+
+        //
+        // Events
+        //
+
+        private void UsersTreeView_Activated(object o, RowActivatedArgs args)
+        {
+            SelectUserTreeView();
+        }
+
+        private void UserSelectedToggle_Toggled(object o, ToggledArgs args)
+        {
+            SelectUserTreeView();
+        }
+
+        private void SelectUserTreeView()
+        {
+            // Get selected item informations.
+            _usersTreeView.Selection.GetSelected(out TreeIter selectedIter);
+
+            Gdk.Pixbuf userPicture = (Gdk.Pixbuf)_tableStore.GetValue(selectedIter, 1);
+
+            string userName = _tableStore.GetValue(selectedIter, 2).ToString().Split("\n")[0];
+            string userId = _tableStore.GetValue(selectedIter, 2).ToString().Split("\n")[1];
+
+            // Unselect the first user.
+            _usersTreeView.Model.GetIterFirst(out TreeIter firstIter);
+            _tableStore.SetValue(firstIter, 0, false);
+            _tableStore.SetValue(firstIter, 3, Gdk.RGBA.Zero);
+
+            // Set new informations.
+            _tableStore.SetValue(selectedIter, 0, true);
+
+            _selectedUserImage.Pixbuf = userPicture;
+            _selectedUserNameEntry.Text = userName;
+            _selectedUserIdLabel.Text = userId;
+            _saveProfileNameButton.Sensitive = false;
+
+            // Open the selected one.
+            _accountManager.OpenUser(new UserId(userId));
+
+            _deleteButton.Sensitive = userId != AccountManager.DefaultUserId.ToString();
+
+            _tableStore.SetValue(selectedIter, 3, _selectedColor);
+        }
+
+        private void SelectedUserNameEntry_KeyReleaseEvent(object o, KeyReleaseEventArgs args)
+        {
+            if (_saveProfileNameButton.Sensitive == false)
+            {
+                _saveProfileNameButton.Sensitive = true;
+            }
+        }
+
+        private void AddButton_Pressed(object sender, EventArgs e)
+        {
+            _tempNewProfileName = GtkDialog.CreateInputDialog(this, "Choose the Profile Name", "Please Enter a Profile Name", MaxProfileNameLength);
+
+            if (_tempNewProfileName != "")
+            {
+                SelectProfileImage(true);
+
+                if (_bufferImageProfile != null)
+                {
+                    AddUser();
+                }
+            }
+        }
+
+        private void DeleteButton_Pressed(object sender, EventArgs e)
+        {
+            if (GtkDialog.CreateChoiceDialog("Delete User Profile", "Are you sure you want to delete the profile ?", "Deleting this profile will also delete all associated save data."))
+            {
+                _accountManager.DeleteUser(GetSelectedUserId());
+
+                RefreshList();
+            }
+        }
+
+        private void EditProfileNameButton_Pressed(object sender, EventArgs e)
+        {
+            _saveProfileNameButton.Sensitive = false;
+
+            _accountManager.SetUserName(GetSelectedUserId(), _selectedUserNameEntry.Text);
+
+            RefreshList();
+        }
+
+        private void ProcessProfileImage(byte[] buffer)
+        {
+            using Image image = Image.Load(buffer);
+
+            image.Mutate(x => x.Resize(256, 256));
+
+            using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
+
+            image.SaveAsJpeg(streamJpg);
+
+            _bufferImageProfile = streamJpg.ToArray();
+        }
+
+        private void ProfileImageFileChooser()
+        {
+            FileChooserNative fileChooser = new("Import Custom Profile Image", this, FileChooserAction.Open, "Import", "Cancel")
+            {
+                SelectMultiple = false,
+            };
+
+            FileFilter filter = new()
+            {
+                Name = "Custom Profile Images",
+            };
+            filter.AddPattern("*.jpg");
+            filter.AddPattern("*.jpeg");
+            filter.AddPattern("*.png");
+            filter.AddPattern("*.bmp");
+
+            fileChooser.AddFilter(filter);
+
+            if (fileChooser.Run() == (int)ResponseType.Accept)
+            {
+                ProcessProfileImage(File.ReadAllBytes(fileChooser.Filename));
+            }
+
+            fileChooser.Dispose();
+        }
+
+        private void SelectProfileImage(bool newUser = false)
+        {
+            if (_contentManager.GetCurrentFirmwareVersion() == null)
+            {
+                ProfileImageFileChooser();
+            }
+            else
+            {
+                Dictionary<int, string> buttons = new()
+                {
+                    { 0, "Import Image File"      },
+                    { 1, "Select Firmware Avatar" },
+                };
+
+                ResponseType responseDialog = GtkDialog.CreateCustomDialog("Profile Image Selection",
+                                                                           "Choose a Profile Image",
+                                                                           "You may import a custom profile image, or select an avatar from the system firmware.",
+                                                                           buttons, MessageType.Question);
+
+                if (responseDialog == 0)
+                {
+                    ProfileImageFileChooser();
+                }
+                else if (responseDialog == (ResponseType)1)
+                {
+                    AvatarWindow avatarWindow = new()
+                    {
+                        NewUser = newUser,
+                    };
+
+                    avatarWindow.DeleteEvent += AvatarWindow_DeleteEvent;
+
+                    avatarWindow.SetSizeRequest((int)(avatarWindow.DefaultWidth * Program.WindowScaleFactor), (int)(avatarWindow.DefaultHeight * Program.WindowScaleFactor));
+                    avatarWindow.Show();
+                }
+            }
+        }
+
+        private void ChangeProfileImageButton_Pressed(object sender, EventArgs e)
+        {
+            if (_contentManager.GetCurrentFirmwareVersion() != null)
+            {
+                _avatarsPreloadingEvent.WaitOne();
+            }
+
+            SelectProfileImage();
+
+            if (_bufferImageProfile != null)
+            {
+                SetUserImage();
+            }
+        }
+
+        private void AvatarWindow_DeleteEvent(object sender, DeleteEventArgs args)
+        {
+            _bufferImageProfile = ((AvatarWindow)sender).SelectedProfileImage;
+
+            if (_bufferImageProfile != null)
+            {
+                if (((AvatarWindow)sender).NewUser)
+                {
+                    AddUser();
+                }
+                else
+                {
+                    SetUserImage();
+                }
+            }
+        }
+
+        private void AddUser()
+        {
+            _accountManager.AddUser(_tempNewProfileName, _bufferImageProfile);
+
+            _bufferImageProfile = null;
+            _tempNewProfileName = "";
+
+            RefreshList();
+        }
+
+        private void SetUserImage()
+        {
+            _accountManager.SetUserImage(GetSelectedUserId(), _bufferImageProfile);
+
+            _bufferImageProfile = null;
+
+            RefreshList();
+        }
+
+        private UserId GetSelectedUserId()
+        {
+            if (_usersTreeView.Model.GetIterFirst(out TreeIter iter))
+            {
+                do
+                {
+                    if ((bool)_tableStore.GetValue(iter, 0))
+                    {
+                        break;
+                    }
+                }
+                while (_usersTreeView.Model.IterNext(ref iter));
+            }
+
+            return new UserId(_tableStore.GetValue(iter, 2).ToString().Split("\n")[1]);
+        }
+
+        private void CloseButton_Pressed(object sender, EventArgs e)
+        {
+            Close();
+        }
+    }
+}
diff --git a/src/Ryujinx/Ui/Applet/ErrorAppletDialog.cs b/src/Ryujinx/Ui/Applet/ErrorAppletDialog.cs
deleted file mode 100644
index c6bcf3f2..00000000
--- a/src/Ryujinx/Ui/Applet/ErrorAppletDialog.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Gtk;
-using Ryujinx.Ui.Common.Configuration;
-using System.Reflection;
-
-namespace Ryujinx.Ui.Applet
-{
-    internal class ErrorAppletDialog : MessageDialog
-    {
-        public ErrorAppletDialog(Window parentWindow, DialogFlags dialogFlags, MessageType messageType, string[] buttons) : base(parentWindow, dialogFlags, messageType, ButtonsType.None, null)
-        {
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            int responseId = 0;
-
-            if (buttons != null)
-            {
-                foreach (string buttonText in buttons)
-                {
-                    AddButton(buttonText, responseId);
-                    responseId++;
-                }
-            }
-            else
-            {
-                AddButton("OK", 0);
-            }
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Applet/GtkDynamicTextInputHandler.cs b/src/Ryujinx/Ui/Applet/GtkDynamicTextInputHandler.cs
deleted file mode 100644
index 3a3da465..00000000
--- a/src/Ryujinx/Ui/Applet/GtkDynamicTextInputHandler.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using Gtk;
-using Ryujinx.HLE.Ui;
-using Ryujinx.Input.GTK3;
-using Ryujinx.Ui.Widgets;
-using System.Threading;
-
-namespace Ryujinx.Ui.Applet
-{
-    /// <summary>
-    /// Class that forwards key events to a GTK Entry so they can be processed into text.
-    /// </summary>
-    internal class GtkDynamicTextInputHandler : IDynamicTextInputHandler
-    {
-        private readonly Window _parent;
-        private readonly OffscreenWindow _inputToTextWindow = new();
-        private readonly RawInputToTextEntry _inputToTextEntry = new();
-
-        private bool _canProcessInput;
-
-        public event DynamicTextChangedHandler TextChangedEvent;
-        public event KeyPressedHandler KeyPressedEvent;
-        public event KeyReleasedHandler KeyReleasedEvent;
-
-        public bool TextProcessingEnabled
-        {
-            get
-            {
-                return Volatile.Read(ref _canProcessInput);
-            }
-
-            set
-            {
-                Volatile.Write(ref _canProcessInput, value);
-            }
-        }
-
-        public GtkDynamicTextInputHandler(Window parent)
-        {
-            _parent = parent;
-            _parent.KeyPressEvent += HandleKeyPressEvent;
-            _parent.KeyReleaseEvent += HandleKeyReleaseEvent;
-
-            _inputToTextWindow.Add(_inputToTextEntry);
-
-            _inputToTextEntry.TruncateMultiline = true;
-
-            // Start with input processing turned off so the text box won't accumulate text 
-            // if the user is playing on the keyboard.
-            _canProcessInput = false;
-        }
-
-        [GLib.ConnectBefore()]
-        private void HandleKeyPressEvent(object o, KeyPressEventArgs args)
-        {
-            var key = (Ryujinx.Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
-
-            if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
-            {
-                return;
-            }
-
-            if (_canProcessInput)
-            {
-                _inputToTextEntry.SendKeyPressEvent(o, args);
-                _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
-                TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
-            }
-        }
-
-        [GLib.ConnectBefore()]
-        private void HandleKeyReleaseEvent(object o, KeyReleaseEventArgs args)
-        {
-            var key = (Ryujinx.Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
-
-            if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
-            {
-                return;
-            }
-
-            if (_canProcessInput)
-            {
-                // TODO (caian): This solution may have problems if the pause is sent after a key press
-                // and before a key release. But for now GTK Entry does not seem to use release events.
-                _inputToTextEntry.SendKeyReleaseEvent(o, args);
-                _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
-                TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
-            }
-        }
-
-        public void SetText(string text, int cursorBegin)
-        {
-            _inputToTextEntry.Text = text;
-            _inputToTextEntry.Position = cursorBegin;
-        }
-
-        public void SetText(string text, int cursorBegin, int cursorEnd)
-        {
-            _inputToTextEntry.Text = text;
-            _inputToTextEntry.SelectRegion(cursorBegin, cursorEnd);
-        }
-
-        public void Dispose()
-        {
-            _parent.KeyPressEvent -= HandleKeyPressEvent;
-            _parent.KeyReleaseEvent -= HandleKeyReleaseEvent;
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Applet/GtkHostUiHandler.cs b/src/Ryujinx/Ui/Applet/GtkHostUiHandler.cs
deleted file mode 100644
index 241e5e6c..00000000
--- a/src/Ryujinx/Ui/Applet/GtkHostUiHandler.cs
+++ /dev/null
@@ -1,200 +0,0 @@
-using Gtk;
-using Ryujinx.HLE.HOS.Applets;
-using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
-using Ryujinx.HLE.Ui;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Threading;
-
-namespace Ryujinx.Ui.Applet
-{
-    internal class GtkHostUiHandler : IHostUiHandler
-    {
-        private readonly Window _parent;
-
-        public IHostUiTheme HostUiTheme { get; }
-
-        public GtkHostUiHandler(Window parent)
-        {
-            _parent = parent;
-
-            HostUiTheme = new GtkHostUiTheme(parent);
-        }
-
-        public bool DisplayMessageDialog(ControllerAppletUiArgs args)
-        {
-            string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
-
-            string message = $"Application requests <b>{playerCount}</b> player(s) with:\n\n"
-                           + $"<tt><b>TYPES:</b> {args.SupportedStyles}</tt>\n\n"
-                           + $"<tt><b>PLAYERS:</b> {string.Join(", ", args.SupportedPlayers)}</tt>\n\n"
-                           + (args.IsDocked ? "Docked mode set. <tt>Handheld</tt> is also invalid.\n\n" : "")
-                           + "<i>Please reconfigure Input now and then press OK.</i>";
-
-            return DisplayMessageDialog("Controller Applet", message);
-        }
-
-        public bool DisplayMessageDialog(string title, string message)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool okPressed = false;
-
-            Application.Invoke(delegate
-            {
-                MessageDialog msgDialog = null;
-
-                try
-                {
-                    msgDialog = new MessageDialog(_parent, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
-                    {
-                        Title = title,
-                        Text = message,
-                        UseMarkup = true,
-                    };
-
-                    msgDialog.SetDefaultSize(400, 0);
-
-                    msgDialog.Response += (object o, ResponseArgs args) =>
-                    {
-                        if (args.ResponseId == ResponseType.Ok)
-                        {
-                            okPressed = true;
-                        }
-
-                        dialogCloseEvent.Set();
-                        msgDialog?.Dispose();
-                    };
-
-                    msgDialog.Show();
-                }
-                catch (Exception ex)
-                {
-                    GtkDialog.CreateErrorDialog($"Error displaying Message Dialog: {ex}");
-
-                    dialogCloseEvent.Set();
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            return okPressed;
-        }
-
-        public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool okPressed = false;
-            bool error = false;
-            string inputText = args.InitialText ?? "";
-
-            Application.Invoke(delegate
-            {
-                try
-                {
-                    var swkbdDialog = new SwkbdAppletDialog(_parent)
-                    {
-                        Title = "Software Keyboard",
-                        Text = args.HeaderText,
-                        SecondaryText = args.SubtitleText,
-                    };
-
-                    swkbdDialog.InputEntry.Text = inputText;
-                    swkbdDialog.InputEntry.PlaceholderText = args.GuideText;
-                    swkbdDialog.OkButton.Label = args.SubmitText;
-
-                    swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
-                    swkbdDialog.SetInputValidation(args.KeyboardMode);
-
-                    if (swkbdDialog.Run() == (int)ResponseType.Ok)
-                    {
-                        inputText = swkbdDialog.InputEntry.Text;
-                        okPressed = true;
-                    }
-
-                    swkbdDialog.Dispose();
-                }
-                catch (Exception ex)
-                {
-                    error = true;
-
-                    GtkDialog.CreateErrorDialog($"Error displaying Software Keyboard: {ex}");
-                }
-                finally
-                {
-                    dialogCloseEvent.Set();
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            userText = error ? null : inputText;
-
-            return error || okPressed;
-        }
-
-        public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value)
-        {
-            device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
-            ((MainWindow)_parent).RendererWidget?.Exit();
-        }
-
-        public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
-        {
-            ManualResetEvent dialogCloseEvent = new(false);
-
-            bool showDetails = false;
-
-            Application.Invoke(delegate
-            {
-                try
-                {
-                    ErrorAppletDialog msgDialog = new(_parent, DialogFlags.DestroyWithParent, MessageType.Error, buttons)
-                    {
-                        Title = title,
-                        Text = message,
-                        UseMarkup = true,
-                        WindowPosition = WindowPosition.CenterAlways,
-                    };
-
-                    msgDialog.SetDefaultSize(400, 0);
-
-                    msgDialog.Response += (object o, ResponseArgs args) =>
-                    {
-                        if (buttons != null)
-                        {
-                            if (buttons.Length > 1)
-                            {
-                                if (args.ResponseId != (ResponseType)(buttons.Length - 1))
-                                {
-                                    showDetails = true;
-                                }
-                            }
-                        }
-
-                        dialogCloseEvent.Set();
-                        msgDialog?.Dispose();
-                    };
-
-                    msgDialog.Show();
-                }
-                catch (Exception ex)
-                {
-                    GtkDialog.CreateErrorDialog($"Error displaying ErrorApplet Dialog: {ex}");
-
-                    dialogCloseEvent.Set();
-                }
-            });
-
-            dialogCloseEvent.WaitOne();
-
-            return showDetails;
-        }
-
-        public IDynamicTextInputHandler CreateDynamicTextInputHandler()
-        {
-            return new GtkDynamicTextInputHandler(_parent);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Applet/GtkHostUiTheme.cs b/src/Ryujinx/Ui/Applet/GtkHostUiTheme.cs
deleted file mode 100644
index 1bc01059..00000000
--- a/src/Ryujinx/Ui/Applet/GtkHostUiTheme.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using Gtk;
-using Ryujinx.HLE.Ui;
-using System.Diagnostics;
-
-namespace Ryujinx.Ui.Applet
-{
-    internal class GtkHostUiTheme : IHostUiTheme
-    {
-        private const int RenderSurfaceWidth = 32;
-        private const int RenderSurfaceHeight = 32;
-
-        public string FontFamily { get; private set; }
-
-        public ThemeColor DefaultBackgroundColor { get; }
-        public ThemeColor DefaultForegroundColor { get; }
-        public ThemeColor DefaultBorderColor { get; }
-        public ThemeColor SelectionBackgroundColor { get; }
-        public ThemeColor SelectionForegroundColor { get; }
-
-        public GtkHostUiTheme(Window parent)
-        {
-            Entry entry = new();
-            entry.SetStateFlags(StateFlags.Selected, true);
-
-            // Get the font and some colors directly from GTK.
-            FontFamily = entry.PangoContext.FontDescription.Family;
-
-            // Get foreground colors from the style context.
-
-            var defaultForegroundColor = entry.StyleContext.GetColor(StateFlags.Normal);
-            var selectedForegroundColor = entry.StyleContext.GetColor(StateFlags.Selected);
-
-            DefaultForegroundColor = new ThemeColor((float)defaultForegroundColor.Alpha, (float)defaultForegroundColor.Red, (float)defaultForegroundColor.Green, (float)defaultForegroundColor.Blue);
-            SelectionForegroundColor = new ThemeColor((float)selectedForegroundColor.Alpha, (float)selectedForegroundColor.Red, (float)selectedForegroundColor.Green, (float)selectedForegroundColor.Blue);
-
-            ListBoxRow row = new();
-            row.SetStateFlags(StateFlags.Selected, true);
-
-            // Request the main thread to render some UI elements to an image to get an approximation for the color.
-            // NOTE (caian): This will only take the color of the top-left corner of the background, which may be incorrect
-            // if someone provides a custom style with a gradient or image.
-
-            using (var surface = new Cairo.ImageSurface(Cairo.Format.Argb32, RenderSurfaceWidth, RenderSurfaceHeight))
-            using (var context = new Cairo.Context(surface))
-            {
-                context.SetSourceRGBA(1, 1, 1, 1);
-                context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
-                context.Fill();
-
-                // The background color must be from the main Window because entry uses a different color.
-                parent.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
-
-                DefaultBackgroundColor = ToThemeColor(surface.Data);
-
-                context.SetSourceRGBA(1, 1, 1, 1);
-                context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
-                context.Fill();
-
-                // Use the background color of the list box row when selected as the text box frame color because they are the
-                // same in the default theme.
-                row.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
-
-                DefaultBorderColor = ToThemeColor(surface.Data);
-            }
-
-            // Use the border color as the text selection color.
-            SelectionBackgroundColor = DefaultBorderColor;
-        }
-
-        private static ThemeColor ToThemeColor(byte[] data)
-        {
-            Debug.Assert(data.Length == 4 * RenderSurfaceWidth * RenderSurfaceHeight);
-
-            // Take the center-bottom pixel of the surface.
-            int position = 4 * (RenderSurfaceWidth * (RenderSurfaceHeight - 1) + RenderSurfaceWidth / 2);
-
-            if (position + 4 > data.Length)
-            {
-                return new ThemeColor(1, 0, 0, 0);
-            }
-
-            float a = data[position + 3] / 255.0f;
-            float r = data[position + 2] / 255.0f;
-            float g = data[position + 1] / 255.0f;
-            float b = data[position + 0] / 255.0f;
-
-            return new ThemeColor(a, r, g, b);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs b/src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs
deleted file mode 100644
index c1f3d77c..00000000
--- a/src/Ryujinx/Ui/Applet/SwkbdAppletDialog.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-using Gtk;
-using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
-using System;
-using System.Linq;
-
-namespace Ryujinx.Ui.Applet
-{
-    public class SwkbdAppletDialog : MessageDialog
-    {
-        private int _inputMin;
-        private int _inputMax;
-#pragma warning disable IDE0052 // Remove unread private member
-        private KeyboardMode _mode;
-#pragma warning restore IDE0052
-
-        private string _validationInfoText = "";
-
-        private Predicate<int> _checkLength = _ => true;
-        private Predicate<string> _checkInput = _ => true;
-
-        private readonly Label _validationInfo;
-
-        public Entry InputEntry { get; }
-        public Button OkButton { get; }
-        public Button CancelButton { get; }
-
-        public SwkbdAppletDialog(Window parent) : base(parent, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.None, null)
-        {
-            SetDefaultSize(300, 0);
-
-            _validationInfo = new Label()
-            {
-                Visible = false,
-            };
-
-            InputEntry = new Entry()
-            {
-                Visible = true,
-            };
-
-            InputEntry.Activated += OnInputActivated;
-            InputEntry.Changed += OnInputChanged;
-
-            OkButton = (Button)AddButton("OK", ResponseType.Ok);
-            CancelButton = (Button)AddButton("Cancel", ResponseType.Cancel);
-
-            ((Box)MessageArea).PackEnd(_validationInfo, true, true, 0);
-            ((Box)MessageArea).PackEnd(InputEntry, true, true, 4);
-        }
-
-        private void ApplyValidationInfo()
-        {
-            _validationInfo.Visible = !string.IsNullOrEmpty(_validationInfoText);
-            _validationInfo.Markup = _validationInfoText;
-        }
-
-        public void SetInputLengthValidation(int min, int max)
-        {
-            _inputMin = Math.Min(min, max);
-            _inputMax = Math.Max(min, max);
-
-            _validationInfo.Visible = false;
-
-            if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
-            {
-                _validationInfo.Visible = false;
-
-                _checkLength = _ => true;
-            }
-            else if (_inputMin > 0 && _inputMax == int.MaxValue)
-            {
-                _validationInfoText = $"<i>Must be at least {_inputMin} characters long.</i> ";
-
-                _checkLength = length => _inputMin <= length;
-            }
-            else
-            {
-                _validationInfoText = $"<i>Must be {_inputMin}-{_inputMax} characters long.</i> ";
-
-                _checkLength = length => _inputMin <= length && length <= _inputMax;
-            }
-
-            ApplyValidationInfo();
-            OnInputChanged(this, EventArgs.Empty);
-        }
-
-        public void SetInputValidation(KeyboardMode mode)
-        {
-            _mode = mode;
-
-            switch (mode)
-            {
-                case KeyboardMode.Numeric:
-                    _validationInfoText += "<i>Must be 0-9 or '.' only.</i>";
-                    _checkInput = text => text.All(NumericCharacterValidation.IsNumeric);
-                    break;
-                case KeyboardMode.Alphabet:
-                    _validationInfoText += "<i>Must be non CJK-characters only.</i>";
-                    _checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
-                    break;
-                case KeyboardMode.ASCII:
-                    _validationInfoText += "<i>Must be ASCII text only.</i>";
-                    _checkInput = text => text.All(char.IsAscii);
-                    break;
-                default:
-                    _checkInput = _ => true;
-                    break;
-            }
-
-            ApplyValidationInfo();
-            OnInputChanged(this, EventArgs.Empty);
-        }
-
-        private void OnInputActivated(object sender, EventArgs e)
-        {
-            if (OkButton.IsSensitive)
-            {
-                Respond(ResponseType.Ok);
-            }
-        }
-
-        private void OnInputChanged(object sender, EventArgs e)
-        {
-            OkButton.Sensitive = _checkLength(InputEntry.Text.Length) && _checkInput(InputEntry.Text);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Helper/MetalHelper.cs b/src/Ryujinx/Ui/Helper/MetalHelper.cs
deleted file mode 100644
index a7af2aed..00000000
--- a/src/Ryujinx/Ui/Helper/MetalHelper.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using Gdk;
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ui.Helper
-{
-    public delegate void UpdateBoundsCallbackDelegate(Window window);
-
-    [SupportedOSPlatform("macos")]
-    static partial class MetalHelper
-    {
-        private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
-
-        private readonly struct Selector
-        {
-            public readonly IntPtr NativePtr;
-
-            public unsafe Selector(string value)
-            {
-                int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
-                byte* data = stackalloc byte[size];
-
-                fixed (char* pValue = value)
-                {
-                    System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
-                }
-
-                NativePtr = sel_registerName(data);
-            }
-
-            public static implicit operator Selector(string value) => new(value);
-        }
-
-        private static unsafe IntPtr GetClass(string value)
-        {
-            int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
-            byte* data = stackalloc byte[size];
-
-            fixed (char* pValue = value)
-            {
-                System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
-            }
-
-            return objc_getClass(data);
-        }
-
-        private struct NsPoint
-        {
-            public double X;
-            public double Y;
-
-            public NsPoint(double x, double y)
-            {
-                X = x;
-                Y = y;
-            }
-        }
-
-        private struct NsRect
-        {
-            public NsPoint Pos;
-            public NsPoint Size;
-
-            public NsRect(double x, double y, double width, double height)
-            {
-                Pos = new NsPoint(x, y);
-                Size = new NsPoint(width, height);
-            }
-        }
-
-        public static IntPtr GetMetalLayer(Display display, Window window, out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
-        {
-            nsView = gdk_quartz_window_get_nsview(window.Handle);
-
-            // Create a new CAMetalLayer.
-            IntPtr layerClass = GetClass("CAMetalLayer");
-            IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
-            objc_msgSend(metalLayer, "init");
-
-            // Create a child NSView to render into.
-            IntPtr nsViewClass = GetClass("NSView");
-            IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
-            objc_msgSend(child, "init", new NsRect());
-
-            // Add it as a child.
-            objc_msgSend(nsView, "addSubview:", child);
-
-            // Make its renderer our metal layer.
-            objc_msgSend(child, "setWantsLayer:", (byte)1);
-            objc_msgSend(child, "setLayer:", metalLayer);
-            objc_msgSend(metalLayer, "setContentsScale:", (double)display.GetMonitorAtWindow(window).ScaleFactor);
-
-            // Set the frame position/location.
-            updateBounds = (Window window) =>
-            {
-                window.GetPosition(out int x, out int y);
-                int width = window.Width;
-                int height = window.Height;
-                objc_msgSend(child, "setFrame:", new NsRect(x, y, width, height));
-            };
-
-            updateBounds(window);
-
-            return metalLayer;
-        }
-
-        [LibraryImport(LibObjCImport)]
-        private static unsafe partial IntPtr sel_registerName(byte* data);
-
-        [LibraryImport(LibObjCImport)]
-        private static unsafe partial IntPtr objc_getClass(byte* data);
-
-        [LibraryImport(LibObjCImport)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector);
-
-        [LibraryImport(LibObjCImport)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
-
-        [LibraryImport(LibObjCImport)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
-
-        [LibraryImport(LibObjCImport)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, NsRect point);
-
-        [LibraryImport(LibObjCImport)]
-        private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
-
-        [LibraryImport(LibObjCImport, EntryPoint = "objc_msgSend")]
-        private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
-
-        [LibraryImport("libgdk-3.0.dylib")]
-        private static partial IntPtr gdk_quartz_window_get_nsview(IntPtr gdkWindow);
-    }
-}
diff --git a/src/Ryujinx/Ui/Helper/SortHelper.cs b/src/Ryujinx/Ui/Helper/SortHelper.cs
deleted file mode 100644
index 4e625f92..00000000
--- a/src/Ryujinx/Ui/Helper/SortHelper.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Gtk;
-using Ryujinx.Ui.Common.Helper;
-using System;
-
-namespace Ryujinx.Ui.Helper
-{
-    static class SortHelper
-    {
-        public static int TimePlayedSort(ITreeModel model, TreeIter a, TreeIter b)
-        {
-            TimeSpan aTimeSpan = ValueFormatUtils.ParseTimeSpan(model.GetValue(a, 5).ToString());
-            TimeSpan bTimeSpan = ValueFormatUtils.ParseTimeSpan(model.GetValue(b, 5).ToString());
-
-            return TimeSpan.Compare(aTimeSpan, bTimeSpan);
-        }
-
-        public static int LastPlayedSort(ITreeModel model, TreeIter a, TreeIter b)
-        {
-            DateTime aDateTime = ValueFormatUtils.ParseDateTime(model.GetValue(a, 6).ToString());
-            DateTime bDateTime = ValueFormatUtils.ParseDateTime(model.GetValue(b, 6).ToString());
-
-            return DateTime.Compare(aDateTime, bDateTime);
-        }
-
-        public static int FileSizeSort(ITreeModel model, TreeIter a, TreeIter b)
-        {
-            long aSize = ValueFormatUtils.ParseFileSize(model.GetValue(a, 8).ToString());
-            long bSize = ValueFormatUtils.ParseFileSize(model.GetValue(b, 8).ToString());
-
-            return aSize.CompareTo(bSize);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Helper/ThemeHelper.cs b/src/Ryujinx/Ui/Helper/ThemeHelper.cs
deleted file mode 100644
index 5cd9ad52..00000000
--- a/src/Ryujinx/Ui/Helper/ThemeHelper.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Gtk;
-using Ryujinx.Common;
-using Ryujinx.Common.Logging;
-using Ryujinx.Ui.Common.Configuration;
-using System.IO;
-
-namespace Ryujinx.Ui.Helper
-{
-    static class ThemeHelper
-    {
-        public static void ApplyTheme()
-        {
-            if (!ConfigurationState.Instance.Ui.EnableCustomTheme)
-            {
-                return;
-            }
-
-            if (File.Exists(ConfigurationState.Instance.Ui.CustomThemePath) && (Path.GetExtension(ConfigurationState.Instance.Ui.CustomThemePath) == ".css"))
-            {
-                CssProvider cssProvider = new();
-
-                cssProvider.LoadFromPath(ConfigurationState.Instance.Ui.CustomThemePath);
-
-                StyleContext.AddProviderForScreen(Gdk.Screen.Default, cssProvider, 800);
-            }
-            else
-            {
-                Logger.Warning?.Print(LogClass.Application, $"The \"custom_theme_path\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid path: \"{ConfigurationState.Instance.Ui.CustomThemePath}\".");
-
-                ConfigurationState.Instance.Ui.CustomThemePath.Value = "";
-                ConfigurationState.Instance.Ui.EnableCustomTheme.Value = false;
-                ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/MainWindow.cs b/src/Ryujinx/Ui/MainWindow.cs
deleted file mode 100644
index 8bfe09cf..00000000
--- a/src/Ryujinx/Ui/MainWindow.cs
+++ /dev/null
@@ -1,1941 +0,0 @@
-using Gtk;
-using LibHac.Common;
-using LibHac.Common.Keys;
-using LibHac.Ncm;
-using LibHac.Ns;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Audio.Backends.Dummy;
-using Ryujinx.Audio.Backends.OpenAL;
-using Ryujinx.Audio.Backends.SDL2;
-using Ryujinx.Audio.Backends.SoundIo;
-using Ryujinx.Audio.Integration;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Multiplayer;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.SystemInterop;
-using Ryujinx.Cpu;
-using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.GAL.Multithreading;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
-using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.HLE.HOS.SystemState;
-using Ryujinx.Input.GTK3;
-using Ryujinx.Input.HLE;
-using Ryujinx.Input.SDL2;
-using Ryujinx.Modules;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Applet;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Helper;
-using Ryujinx.Ui.Widgets;
-using Ryujinx.Ui.Windows;
-using Silk.NET.Vulkan;
-using SPB.Graphics.Vulkan;
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using GUI = Gtk.Builder.ObjectAttribute;
-using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
-
-namespace Ryujinx.Ui
-{
-    public class MainWindow : Window
-    {
-        private readonly VirtualFileSystem _virtualFileSystem;
-        private readonly ContentManager _contentManager;
-        private readonly AccountManager _accountManager;
-        private readonly LibHacHorizonManager _libHacHorizonManager;
-
-        private UserChannelPersistence _userChannelPersistence;
-
-        private HLE.Switch _emulationContext;
-
-        private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
-
-        private readonly ApplicationLibrary _applicationLibrary;
-        private readonly GtkHostUiHandler _uiHandler;
-        private readonly AutoResetEvent _deviceExitStatus;
-        private readonly ListStore _tableStore;
-
-        private bool _updatingGameTable;
-        private bool _gameLoaded;
-        private bool _ending;
-
-        private string _currentEmulatedGamePath = null;
-
-        private string _lastScannedAmiiboId = "";
-        private bool _lastScannedAmiiboShowAll = false;
-
-        public RendererWidgetBase RendererWidget;
-        public InputManager InputManager;
-
-        public bool IsFocused;
-
-#pragma warning disable CS0169, CS0649, IDE0044, IDE0051 // Field is never assigned to, Add readonly modifier, Remove unused private member
-
-        [GUI] public MenuItem ExitMenuItem;
-        [GUI] public MenuItem UpdateMenuItem;
-        [GUI] MenuBar _menuBar;
-        [GUI] Box _footerBox;
-        [GUI] Box _statusBar;
-        [GUI] MenuItem _optionMenu;
-        [GUI] MenuItem _manageUserProfiles;
-        [GUI] MenuItem _fileMenu;
-        [GUI] MenuItem _loadApplicationFile;
-        [GUI] MenuItem _loadApplicationFolder;
-        [GUI] MenuItem _appletMenu;
-        [GUI] MenuItem _actionMenu;
-        [GUI] MenuItem _pauseEmulation;
-        [GUI] MenuItem _resumeEmulation;
-        [GUI] MenuItem _stopEmulation;
-        [GUI] MenuItem _simulateWakeUpMessage;
-        [GUI] MenuItem _scanAmiibo;
-        [GUI] MenuItem _takeScreenshot;
-        [GUI] MenuItem _hideUi;
-        [GUI] MenuItem _fullScreen;
-        [GUI] CheckMenuItem _startFullScreen;
-        [GUI] CheckMenuItem _showConsole;
-        [GUI] CheckMenuItem _favToggle;
-        [GUI] MenuItem _firmwareInstallDirectory;
-        [GUI] MenuItem _firmwareInstallFile;
-        [GUI] MenuItem _fileTypesSubMenu;
-        [GUI] Label _fifoStatus;
-        [GUI] CheckMenuItem _iconToggle;
-        [GUI] CheckMenuItem _developerToggle;
-        [GUI] CheckMenuItem _appToggle;
-        [GUI] CheckMenuItem _timePlayedToggle;
-        [GUI] CheckMenuItem _versionToggle;
-        [GUI] CheckMenuItem _lastPlayedToggle;
-        [GUI] CheckMenuItem _fileExtToggle;
-        [GUI] CheckMenuItem _pathToggle;
-        [GUI] CheckMenuItem _fileSizeToggle;
-        [GUI] CheckMenuItem _nspShown;
-        [GUI] CheckMenuItem _pfs0Shown;
-        [GUI] CheckMenuItem _xciShown;
-        [GUI] CheckMenuItem _ncaShown;
-        [GUI] CheckMenuItem _nroShown;
-        [GUI] CheckMenuItem _nsoShown;
-        [GUI] Label _gpuBackend;
-        [GUI] Label _dockedMode;
-        [GUI] Label _aspectRatio;
-        [GUI] Label _gameStatus;
-        [GUI] TreeView _gameTable;
-        [GUI] TreeSelection _gameTableSelection;
-        [GUI] ScrolledWindow _gameTableWindow;
-        [GUI] Label _gpuName;
-        [GUI] Label _progressLabel;
-        [GUI] Label _firmwareVersionLabel;
-        [GUI] Gtk.ProgressBar _progressBar;
-        [GUI] Box _viewBox;
-        [GUI] Label _vSyncStatus;
-        [GUI] Label _volumeStatus;
-        [GUI] Box _listStatusBox;
-        [GUI] Label _loadingStatusLabel;
-        [GUI] Gtk.ProgressBar _loadingStatusBar;
-
-#pragma warning restore CS0649, IDE0044, CS0169, IDE0051
-
-        public MainWindow() : this(new Builder("Ryujinx.Ui.MainWindow.glade")) { }
-
-        private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("_mainWin"))
-        {
-            builder.Autoconnect(this);
-
-            // Apply custom theme if needed.
-            ThemeHelper.ApplyTheme();
-
-            SetWindowSizePosition();
-
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-            Title = $"Ryujinx {Program.Version}";
-
-            // Hide emulation context status bar.
-            _statusBar.Hide();
-
-            // Instantiate HLE objects.
-            _virtualFileSystem = VirtualFileSystem.CreateInstance();
-            _libHacHorizonManager = new LibHacHorizonManager();
-
-            _libHacHorizonManager.InitializeFsServer(_virtualFileSystem);
-            _libHacHorizonManager.InitializeArpServer();
-            _libHacHorizonManager.InitializeBcatServer();
-            _libHacHorizonManager.InitializeSystemClients();
-
-            // Save data created before we supported extra data in directory save data will not work properly if
-            // given empty extra data. Luckily some of that extra data can be created using the data from the
-            // save data indexer, which should be enough to check access permissions for user saves.
-            // Every single save data's extra data will be checked and fixed if needed each time the emulator is opened.
-            // Consider removing this at some point in the future when we don't need to worry about old saves.
-            VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient);
-
-            _contentManager = new ContentManager(_virtualFileSystem);
-            _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, CommandLineState.Profile);
-            _userChannelPersistence = new UserChannelPersistence();
-
-            // Instantiate GUI objects.
-            _applicationLibrary = new ApplicationLibrary(_virtualFileSystem);
-            _uiHandler = new GtkHostUiHandler(this);
-            _deviceExitStatus = new AutoResetEvent(false);
-
-            WindowStateEvent += WindowStateEvent_Changed;
-            DeleteEvent += Window_Close;
-            FocusInEvent += MainWindow_FocusInEvent;
-            FocusOutEvent += MainWindow_FocusOutEvent;
-
-            _applicationLibrary.ApplicationAdded += Application_Added;
-            _applicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
-
-            _fileMenu.StateChanged += FileMenu_StateChanged;
-            _actionMenu.StateChanged += ActionMenu_StateChanged;
-            _optionMenu.StateChanged += OptionMenu_StateChanged;
-
-            _gameTable.ButtonReleaseEvent += Row_Clicked;
-            _fullScreen.Activated += FullScreen_Toggled;
-
-            RendererWidgetBase.StatusUpdatedEvent += Update_StatusBar;
-
-            ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
-            ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
-            ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
-            ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
-
-            ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerMode;
-            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateMultiplayerLanInterfaceId;
-
-            if (ConfigurationState.Instance.Ui.StartFullscreen)
-            {
-                _startFullScreen.Active = true;
-            }
-
-            _showConsole.Active = ConfigurationState.Instance.Ui.ShowConsole.Value;
-            _showConsole.Visible = ConsoleHelper.SetConsoleWindowStateSupported;
-
-            _actionMenu.Sensitive = false;
-            _pauseEmulation.Sensitive = false;
-            _resumeEmulation.Sensitive = false;
-
-            _nspShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value;
-            _pfs0Shown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value;
-            _xciShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value;
-            _ncaShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value;
-            _nroShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value;
-            _nsoShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value;
-
-            _nspShown.Toggled += NSP_Shown_Toggled;
-            _pfs0Shown.Toggled += PFS0_Shown_Toggled;
-            _xciShown.Toggled += XCI_Shown_Toggled;
-            _ncaShown.Toggled += NCA_Shown_Toggled;
-            _nroShown.Toggled += NRO_Shown_Toggled;
-            _nsoShown.Toggled += NSO_Shown_Toggled;
-
-            _fileTypesSubMenu.Visible = FileAssociationHelper.IsTypeAssociationSupported;
-
-            if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn)
-            {
-                _favToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.IconColumn)
-            {
-                _iconToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn)
-            {
-                _appToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn)
-            {
-                _developerToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.VersionColumn)
-            {
-                _versionToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn)
-            {
-                _timePlayedToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn)
-            {
-                _lastPlayedToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn)
-            {
-                _fileExtToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn)
-            {
-                _fileSizeToggle.Active = true;
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn)
-            {
-                _pathToggle.Active = true;
-            }
-
-            _favToggle.Toggled += Fav_Toggled;
-            _iconToggle.Toggled += Icon_Toggled;
-            _appToggle.Toggled += App_Toggled;
-            _developerToggle.Toggled += Developer_Toggled;
-            _versionToggle.Toggled += Version_Toggled;
-            _timePlayedToggle.Toggled += TimePlayed_Toggled;
-            _lastPlayedToggle.Toggled += LastPlayed_Toggled;
-            _fileExtToggle.Toggled += FileExt_Toggled;
-            _fileSizeToggle.Toggled += FileSize_Toggled;
-            _pathToggle.Toggled += Path_Toggled;
-
-            _gameTable.Model = _tableStore = new ListStore(
-                typeof(bool),
-                typeof(Gdk.Pixbuf),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(string),
-                typeof(BlitStruct<ApplicationControlProperty>));
-
-            _tableStore.SetSortFunc(5, SortHelper.TimePlayedSort);
-            _tableStore.SetSortFunc(6, SortHelper.LastPlayedSort);
-            _tableStore.SetSortFunc(8, SortHelper.FileSizeSort);
-
-            int columnId = ConfigurationState.Instance.Ui.ColumnSort.SortColumnId;
-            bool ascending = ConfigurationState.Instance.Ui.ColumnSort.SortAscending;
-
-            _tableStore.SetSortColumnId(columnId, ascending ? SortType.Ascending : SortType.Descending);
-
-            _gameTable.EnableSearch = true;
-            _gameTable.SearchColumn = 2;
-            _gameTable.SearchEqualFunc = (model, col, key, iter) => !((string)model.GetValue(iter, col)).Contains(key, StringComparison.InvariantCultureIgnoreCase);
-
-            _hideUi.Label = _hideUi.Label.Replace("SHOWUIKEY", ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi.ToString());
-
-            UpdateColumns();
-            UpdateGameTable();
-
-            ConfigurationState.Instance.Ui.GameDirs.Event += (sender, args) =>
-            {
-                if (args.OldValue != args.NewValue)
-                {
-                    UpdateGameTable();
-                }
-            };
-
-            Task.Run(RefreshFirmwareLabel);
-
-            InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver());
-        }
-
-        private void UpdateMultiplayerLanInterfaceId(object sender, ReactiveEventArgs<string> args)
-        {
-            if (_emulationContext != null)
-            {
-                _emulationContext.Configuration.MultiplayerLanInterfaceId = args.NewValue;
-            }
-        }
-
-        private void UpdateMultiplayerMode(object sender, ReactiveEventArgs<MultiplayerMode> args)
-        {
-            if (_emulationContext != null)
-            {
-                _emulationContext.Configuration.MultiplayerMode = args.NewValue;
-            }
-        }
-
-        private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
-        {
-            if (_emulationContext != null)
-            {
-                _emulationContext.Configuration.IgnoreMissingServices = args.NewValue;
-            }
-        }
-
-        private void UpdateAspectRatioState(object sender, ReactiveEventArgs<AspectRatio> args)
-        {
-            if (_emulationContext != null)
-            {
-                _emulationContext.Configuration.AspectRatio = args.NewValue;
-            }
-        }
-
-        private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
-        {
-            _emulationContext?.System.ChangeDockedModeState(e.NewValue);
-        }
-
-        private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
-        {
-            _emulationContext?.SetVolume(e.NewValue);
-        }
-
-        private void WindowStateEvent_Changed(object o, WindowStateEventArgs args)
-        {
-            _fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen";
-        }
-
-        private void MainWindow_FocusOutEvent(object o, FocusOutEventArgs args)
-        {
-            IsFocused = false;
-        }
-
-        private void MainWindow_FocusInEvent(object o, FocusInEventArgs args)
-        {
-            IsFocused = true;
-        }
-
-        private void UpdateColumns()
-        {
-            foreach (TreeViewColumn column in _gameTable.Columns)
-            {
-                _gameTable.RemoveColumn(column);
-            }
-
-            CellRendererToggle favToggle = new();
-            favToggle.Toggled += FavToggle_Toggled;
-
-            if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn)
-            {
-                _gameTable.AppendColumn("Fav", favToggle, "active", 0);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.IconColumn)
-            {
-                _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 1);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn)
-            {
-                _gameTable.AppendColumn("Application", new CellRendererText(), "text", 2);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn)
-            {
-                _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 3);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.VersionColumn)
-            {
-                _gameTable.AppendColumn("Version", new CellRendererText(), "text", 4);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn)
-            {
-                _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 5);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn)
-            {
-                _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 6);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn)
-            {
-                _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 7);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn)
-            {
-                _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 8);
-            }
-            if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn)
-            {
-                _gameTable.AppendColumn("Path", new CellRendererText(), "text", 9);
-            }
-
-            foreach (TreeViewColumn column in _gameTable.Columns)
-            {
-                switch (column.Title)
-                {
-                    case "Fav":
-                        column.SortColumnId = 0;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Application":
-                        column.SortColumnId = 2;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Developer":
-                        column.SortColumnId = 3;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Version":
-                        column.SortColumnId = 4;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Time Played":
-                        column.SortColumnId = 5;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Last Played":
-                        column.SortColumnId = 6;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "File Ext":
-                        column.SortColumnId = 7;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "File Size":
-                        column.SortColumnId = 8;
-                        column.Clicked += Column_Clicked;
-                        break;
-                    case "Path":
-                        column.SortColumnId = 9;
-                        column.Clicked += Column_Clicked;
-                        break;
-                }
-            }
-        }
-
-        protected override void OnDestroyed()
-        {
-            InputManager.Dispose();
-        }
-
-        private void InitializeSwitchInstance()
-        {
-            _virtualFileSystem.ReloadKeySet();
-
-            IRenderer renderer;
-
-            if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
-            {
-                string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
-                renderer = new Graphics.Vulkan.VulkanRenderer(Vk.GetApi(), CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
-            }
-            else
-            {
-                renderer = new Graphics.OpenGL.OpenGLRenderer();
-            }
-
-            BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
-
-            bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
-
-            if (threadedGAL)
-            {
-                renderer = new ThreadedRenderer(renderer);
-            }
-
-            Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {threadedGAL}");
-
-            IHardwareDeviceDriver deviceDriver = new DummyHardwareDeviceDriver();
-
-            if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SDL2)
-            {
-                if (SDL2HardwareDeviceDriver.IsSupported)
-                {
-                    deviceDriver = new SDL2HardwareDeviceDriver();
-                }
-                else
-                {
-                    Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
-
-                    if (OpenALHardwareDeviceDriver.IsSupported)
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
-
-                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
-                        SaveConfig();
-
-                        deviceDriver = new OpenALHardwareDeviceDriver();
-                    }
-                    else
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SoundIO.");
-
-                        if (SoundIoHardwareDeviceDriver.IsSupported)
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
-
-                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
-                            SaveConfig();
-
-                            deviceDriver = new SoundIoHardwareDeviceDriver();
-                        }
-                        else
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
-                        }
-                    }
-                }
-            }
-            else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SoundIo)
-            {
-                if (SoundIoHardwareDeviceDriver.IsSupported)
-                {
-                    deviceDriver = new SoundIoHardwareDeviceDriver();
-                }
-                else
-                {
-                    Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, trying to fall back to SDL2.");
-
-                    if (SDL2HardwareDeviceDriver.IsSupported)
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
-
-                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
-                        SaveConfig();
-
-                        deviceDriver = new SDL2HardwareDeviceDriver();
-                    }
-                    else
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
-
-                        if (OpenALHardwareDeviceDriver.IsSupported)
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
-
-                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
-                            SaveConfig();
-
-                            deviceDriver = new OpenALHardwareDeviceDriver();
-                        }
-                        else
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, falling back to dummy audio out.");
-                        }
-                    }
-                }
-            }
-            else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.OpenAl)
-            {
-                if (OpenALHardwareDeviceDriver.IsSupported)
-                {
-                    deviceDriver = new OpenALHardwareDeviceDriver();
-                }
-                else
-                {
-                    Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SDL2.");
-
-                    if (SDL2HardwareDeviceDriver.IsSupported)
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
-
-                        ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
-                        SaveConfig();
-
-                        deviceDriver = new SDL2HardwareDeviceDriver();
-                    }
-                    else
-                    {
-                        Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to SoundIO.");
-
-                        if (SoundIoHardwareDeviceDriver.IsSupported)
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
-
-                            ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
-                            SaveConfig();
-
-                            deviceDriver = new SoundIoHardwareDeviceDriver();
-                        }
-                        else
-                        {
-                            Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
-                        }
-                    }
-                }
-            }
-
-            var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value
-                ? HLE.MemoryConfiguration.MemoryConfiguration6GiB
-                : HLE.MemoryConfiguration.MemoryConfiguration4GiB;
-
-            IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None;
-
-            HLE.HLEConfiguration configuration = new(_virtualFileSystem,
-                _libHacHorizonManager,
-                _contentManager,
-                _accountManager,
-                _userChannelPersistence,
-                renderer,
-                deviceDriver,
-                memoryConfiguration,
-                _uiHandler,
-                (SystemLanguage)ConfigurationState.Instance.System.Language.Value,
-                (RegionCode)ConfigurationState.Instance.System.Region.Value,
-                ConfigurationState.Instance.Graphics.EnableVsync,
-                ConfigurationState.Instance.System.EnableDockedMode,
-                ConfigurationState.Instance.System.EnablePtc,
-                ConfigurationState.Instance.System.EnableInternetAccess,
-                fsIntegrityCheckLevel,
-                ConfigurationState.Instance.System.FsGlobalAccessLogMode,
-                ConfigurationState.Instance.System.SystemTimeOffset,
-                ConfigurationState.Instance.System.TimeZone,
-                ConfigurationState.Instance.System.MemoryManagerMode,
-                ConfigurationState.Instance.System.IgnoreMissingServices,
-                ConfigurationState.Instance.Graphics.AspectRatio,
-                ConfigurationState.Instance.System.AudioVolume,
-                ConfigurationState.Instance.System.UseHypervisor,
-                ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
-                ConfigurationState.Instance.Multiplayer.Mode);
-
-            _emulationContext = new HLE.Switch(configuration);
-        }
-
-        private SurfaceKHR CreateVulkanSurface(Instance instance, Vk vk)
-        {
-            return new SurfaceKHR((ulong)((VulkanRenderer)RendererWidget).CreateWindowSurface(instance.Handle));
-        }
-
-        private void SetupProgressUiHandlers()
-        {
-            if (_emulationContext.Processes.ActiveApplication.DiskCacheLoadState != null)
-            {
-                _emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged -= ProgressHandler;
-                _emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged += ProgressHandler;
-            }
-
-            _emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
-            _emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
-        }
-
-        private void ProgressHandler<T>(T state, int current, int total) where T : Enum
-        {
-            bool visible;
-            string label;
-
-            switch (state)
-            {
-                case LoadState ptcState:
-                    visible = ptcState != LoadState.Loaded;
-                    label = $"PTC : {current}/{total}";
-                    break;
-                case ShaderCacheLoadingState shaderCacheState:
-                    visible = shaderCacheState != ShaderCacheLoadingState.Loaded;
-                    label = $"Shaders : {current}/{total}";
-                    break;
-                default:
-                    throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
-            }
-
-            Application.Invoke(delegate
-            {
-                _loadingStatusLabel.Text = label;
-                _loadingStatusBar.Fraction = total > 0 ? (double)current / total : 0;
-                _loadingStatusBar.Visible = visible;
-                _loadingStatusLabel.Visible = visible;
-            });
-        }
-
-        public void UpdateGameTable()
-        {
-            if (_updatingGameTable || _gameLoaded)
-            {
-                return;
-            }
-
-            _updatingGameTable = true;
-
-            _tableStore.Clear();
-
-            Thread applicationLibraryThread = new(() =>
-            {
-                _applicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs, ConfigurationState.Instance.System.Language);
-
-                _updatingGameTable = false;
-            })
-            {
-                Name = "GUI.ApplicationLibraryThread",
-                IsBackground = true,
-            };
-            applicationLibraryThread.Start();
-        }
-
-        [Conditional("RELEASE")]
-        public void PerformanceCheck()
-        {
-            if (ConfigurationState.Instance.Logger.EnableTrace.Value)
-            {
-                MessageDialog debugWarningDialog = new(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
-                {
-                    Title = "Ryujinx - Warning",
-                    Text = "You have trace logging enabled, which is designed to be used by developers only.",
-                    SecondaryText = "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?",
-                };
-
-                if (debugWarningDialog.Run() == (int)ResponseType.Yes)
-                {
-                    ConfigurationState.Instance.Logger.EnableTrace.Value = false;
-                    SaveConfig();
-                }
-
-                debugWarningDialog.Dispose();
-            }
-
-            if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value))
-            {
-                MessageDialog shadersDumpWarningDialog = new(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
-                {
-                    Title = "Ryujinx - Warning",
-                    Text = "You have shader dumping enabled, which is designed to be used by developers only.",
-                    SecondaryText = "For optimal performance, it's recommended to disable shader dumping. Would you like to disable shader dumping now?",
-                };
-
-                if (shadersDumpWarningDialog.Run() == (int)ResponseType.Yes)
-                {
-                    ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = "";
-                    SaveConfig();
-                }
-
-                shadersDumpWarningDialog.Dispose();
-            }
-        }
-
-        private bool LoadApplication(string path, bool isFirmwareTitle)
-        {
-            SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
-
-            if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError))
-            {
-                if (SetupValidator.CanFixStartApplication(_contentManager, path, userError, out firmwareVersion))
-                {
-                    string message = $"Would you like to install the firmware embedded in this game? (Firmware {firmwareVersion.VersionString})";
-
-                    ResponseType responseDialog = (ResponseType)GtkDialog.CreateConfirmationDialog("No Firmware Installed", message).Run();
-
-                    if (responseDialog != ResponseType.Yes || !SetupValidator.TryFixStartApplication(_contentManager, path, userError, out _))
-                    {
-                        UserErrorDialog.CreateUserErrorDialog(userError);
-
-                        return false;
-                    }
-
-                    // Tell the user that we installed a firmware for them.
-
-                    firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
-
-                    RefreshFirmwareLabel();
-
-                    message = $"No installed firmware was found but Ryujinx was able to install firmware {firmwareVersion.VersionString} from the provided game.\nThe emulator will now start.";
-
-                    GtkDialog.CreateInfoDialog($"Firmware {firmwareVersion.VersionString} was installed", message);
-                }
-                else
-                {
-                    UserErrorDialog.CreateUserErrorDialog(userError);
-
-                    return false;
-                }
-            }
-
-            Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
-
-            if (isFirmwareTitle)
-            {
-                Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
-
-                return _emulationContext.LoadNca(path);
-            }
-
-            if (Directory.Exists(path))
-            {
-                string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
-
-                if (romFsFiles.Length == 0)
-                {
-                    romFsFiles = Directory.GetFiles(path, "*.romfs");
-                }
-
-                if (romFsFiles.Length > 0)
-                {
-                    Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
-
-                    return _emulationContext.LoadCart(path, romFsFiles[0]);
-                }
-
-                Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS.");
-
-                return _emulationContext.LoadCart(path);
-            }
-
-            if (File.Exists(path))
-            {
-                switch (System.IO.Path.GetExtension(path).ToLowerInvariant())
-                {
-                    case ".xci":
-                        Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
-
-                        return _emulationContext.LoadXci(path);
-                    case ".nca":
-                        Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
-
-                        return _emulationContext.LoadNca(path);
-                    case ".nsp":
-                    case ".pfs0":
-                        Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
-
-                        return _emulationContext.LoadNsp(path);
-                    default:
-                        Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
-                        try
-                        {
-                            return _emulationContext.LoadProgram(path);
-                        }
-                        catch (ArgumentOutOfRangeException)
-                        {
-                            Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");
-
-                            return false;
-                        }
-                }
-            }
-
-            Logger.Warning?.Print(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
-
-            return false;
-        }
-
-        public void RunApplication(string path, bool startFullscreen = false)
-        {
-            if (_gameLoaded)
-            {
-                GtkDialog.CreateInfoDialog("A game has already been loaded", "Please stop emulation or close the emulator before launching another game.");
-            }
-            else
-            {
-                PerformanceCheck();
-
-                Logger.RestartTime();
-
-                RendererWidget = CreateRendererWidget();
-
-                SwitchToRenderWidget(startFullscreen);
-
-                InitializeSwitchInstance();
-
-                UpdateGraphicsConfig();
-
-                bool isFirmwareTitle = false;
-
-                if (path.StartsWith("@SystemContent"))
-                {
-                    path = VirtualFileSystem.SwitchPathToSystemPath(path);
-
-                    isFirmwareTitle = true;
-                }
-
-                if (!LoadApplication(path, isFirmwareTitle))
-                {
-                    _emulationContext.Dispose();
-                    SwitchToGameTable();
-
-                    return;
-                }
-
-                SetupProgressUiHandlers();
-
-                _currentEmulatedGamePath = path;
-
-                _deviceExitStatus.Reset();
-
-                Thread windowThread = new(CreateGameWindow)
-                {
-                    Name = "GUI.WindowThread",
-                };
-
-                windowThread.Start();
-
-                _gameLoaded = true;
-                _actionMenu.Sensitive = true;
-                UpdateMenuItem.Sensitive = false;
-
-                _lastScannedAmiiboId = "";
-
-                _firmwareInstallFile.Sensitive = false;
-                _firmwareInstallDirectory.Sensitive = false;
-
-                DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Processes.ActiveApplication.ProgramIdText,
-                                                              _emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString());
-
-                ApplicationLibrary.LoadAndSaveMetaData(_emulationContext.Processes.ActiveApplication.ProgramIdText, appMetadata =>
-                {
-                    appMetadata.UpdatePreGame();
-                });
-            }
-        }
-
-        private RendererWidgetBase CreateRendererWidget()
-        {
-            if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
-            {
-                return new VulkanRenderer(InputManager, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
-            }
-            else
-            {
-                return new OpenGLRenderer(InputManager, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
-            }
-        }
-
-        private void SwitchToRenderWidget(bool startFullscreen = false)
-        {
-            _viewBox.Remove(_gameTableWindow);
-            RendererWidget.Expand = true;
-            _viewBox.Child = RendererWidget;
-
-            RendererWidget.ShowAll();
-            EditFooterForGameRenderer();
-
-            if (Window.State.HasFlag(Gdk.WindowState.Fullscreen))
-            {
-                ToggleExtraWidgets(false);
-            }
-            else if (startFullscreen || ConfigurationState.Instance.Ui.StartFullscreen.Value)
-            {
-                FullScreen_Toggled(null, null);
-            }
-        }
-
-        private void SwitchToGameTable()
-        {
-            if (Window.State.HasFlag(Gdk.WindowState.Fullscreen))
-            {
-                ToggleExtraWidgets(true);
-            }
-
-            RendererWidget.Exit();
-
-            if (RendererWidget.Window != Window && RendererWidget.Window != null)
-            {
-                RendererWidget.Window.Dispose();
-            }
-
-            RendererWidget.Dispose();
-
-            if (OperatingSystem.IsWindows())
-            {
-                _windowsMultimediaTimerResolution?.Dispose();
-                _windowsMultimediaTimerResolution = null;
-            }
-
-            DisplaySleep.Restore();
-
-            _viewBox.Remove(RendererWidget);
-            _viewBox.Add(_gameTableWindow);
-
-            _gameTableWindow.Expand = true;
-
-            Window.Title = $"Ryujinx {Program.Version}";
-
-            _emulationContext = null;
-            _gameLoaded = false;
-            RendererWidget = null;
-
-            DiscordIntegrationModule.SwitchToMainMenu();
-
-            RecreateFooterForMenu();
-
-            UpdateColumns();
-            UpdateGameTable();
-
-            RefreshFirmwareLabel();
-            HandleRelaunch();
-        }
-
-        private void CreateGameWindow()
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
-            }
-
-            DisplaySleep.Prevent();
-
-            RendererWidget.Initialize(_emulationContext);
-
-            RendererWidget.WaitEvent.WaitOne();
-
-            RendererWidget.Start();
-
-            _emulationContext.Dispose();
-            _deviceExitStatus.Set();
-
-            // NOTE: Everything that is here will not be executed when you close the UI.
-            Application.Invoke(delegate
-            {
-                SwitchToGameTable();
-            });
-        }
-
-        private void RecreateFooterForMenu()
-        {
-            _listStatusBox.Show();
-            _statusBar.Hide();
-        }
-
-        private void EditFooterForGameRenderer()
-        {
-            _listStatusBox.Hide();
-            _statusBar.Show();
-        }
-
-        public void ToggleExtraWidgets(bool show)
-        {
-            if (RendererWidget != null)
-            {
-                if (show)
-                {
-                    _menuBar.ShowAll();
-                    _footerBox.Show();
-                    _statusBar.Show();
-                }
-                else
-                {
-                    _menuBar.Hide();
-                    _footerBox.Hide();
-                }
-            }
-        }
-
-        private void UpdateGameMetadata(string titleId)
-        {
-            if (_gameLoaded)
-            {
-                ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
-                {
-                    appMetadata.UpdatePostGame();
-                });
-            }
-        }
-
-        public static void UpdateGraphicsConfig()
-        {
-            int resScale = ConfigurationState.Instance.Graphics.ResScale;
-            float resScaleCustom = ConfigurationState.Instance.Graphics.ResScaleCustom;
-
-            Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale;
-            Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
-            Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
-            Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
-            Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
-            Graphics.Gpu.GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
-        }
-
-        public void UpdateInternetAccess()
-        {
-            if (_gameLoaded)
-            {
-                _emulationContext.Configuration.EnableInternetAccess = ConfigurationState.Instance.System.EnableInternetAccess.Value;
-            }
-        }
-
-        public static void SaveConfig()
-        {
-            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-        }
-
-        private void End()
-        {
-            if (_ending)
-            {
-                return;
-            }
-
-            _ending = true;
-
-            if (_emulationContext != null)
-            {
-                UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
-
-                if (RendererWidget != null)
-                {
-                    // We tell the widget that we are exiting.
-                    RendererWidget.Exit();
-
-                    // Wait for the other thread to dispose the HLE context before exiting.
-                    _deviceExitStatus.WaitOne();
-                    RendererWidget.Dispose();
-                }
-            }
-
-            Dispose();
-
-            Program.Exit();
-            Application.Quit();
-        }
-
-        //
-        // Events
-        //
-        private void Application_Added(object sender, ApplicationAddedEventArgs args)
-        {
-            Application.Invoke(delegate
-            {
-                _tableStore.AppendValues(
-                    args.AppData.Favorite,
-                    new Gdk.Pixbuf(args.AppData.Icon, 75, 75),
-                    $"{args.AppData.TitleName}\n{args.AppData.TitleId.ToUpper()}",
-                    args.AppData.Developer,
-                    args.AppData.Version,
-                    args.AppData.TimePlayedString,
-                    args.AppData.LastPlayedString,
-                    args.AppData.FileExtension,
-                    args.AppData.FileSizeString,
-                    args.AppData.Path,
-                    args.AppData.ControlHolder);
-            });
-        }
-
-        private void ApplicationCount_Updated(object sender, ApplicationCountUpdatedEventArgs args)
-        {
-            Application.Invoke(delegate
-            {
-                _progressLabel.Text = $"{args.NumAppsLoaded}/{args.NumAppsFound} Games Loaded";
-                float barValue = 0;
-
-                if (args.NumAppsFound != 0)
-                {
-                    barValue = (float)args.NumAppsLoaded / args.NumAppsFound;
-                }
-
-                _progressBar.Fraction = barValue;
-
-                // Reset the vertical scrollbar to the top when titles finish loading
-                if (args.NumAppsLoaded == args.NumAppsFound)
-                {
-                    _gameTableWindow.Vadjustment.Value = 0;
-                }
-            });
-        }
-
-        private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
-        {
-            Application.Invoke(delegate
-            {
-                _gameStatus.Text = args.GameStatus;
-                _fifoStatus.Text = args.FifoStatus;
-                _gpuName.Text = args.GpuName;
-                _dockedMode.Text = args.DockedMode;
-                _aspectRatio.Text = args.AspectRatio;
-                _gpuBackend.Text = args.GpuBackend;
-                _volumeStatus.Text = GetVolumeLabelText(args.Volume);
-
-                if (args.VSyncEnabled)
-                {
-                    _vSyncStatus.Attributes = new Pango.AttrList();
-                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(11822, 60138, 51657));
-                }
-                else
-                {
-                    _vSyncStatus.Attributes = new Pango.AttrList();
-                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(ushort.MaxValue, 17733, 21588));
-                }
-            });
-        }
-
-        private void FavToggle_Toggled(object sender, ToggledArgs args)
-        {
-            _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path));
-
-            string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
-            bool newToggleValue = !(bool)_tableStore.GetValue(treeIter, 0);
-
-            _tableStore.SetValue(treeIter, 0, newToggleValue);
-
-            ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
-            {
-                appMetadata.Favorite = newToggleValue;
-            });
-        }
-
-        private void Column_Clicked(object sender, EventArgs args)
-        {
-            TreeViewColumn column = (TreeViewColumn)sender;
-
-            ConfigurationState.Instance.Ui.ColumnSort.SortColumnId.Value = column.SortColumnId;
-            ConfigurationState.Instance.Ui.ColumnSort.SortAscending.Value = column.SortOrder == SortType.Ascending;
-
-            SaveConfig();
-        }
-
-        private void Row_Activated(object sender, RowActivatedArgs args)
-        {
-            _gameTableSelection.GetSelected(out TreeIter treeIter);
-
-            string path = (string)_tableStore.GetValue(treeIter, 9);
-
-            RunApplication(path);
-        }
-
-        private void VSyncStatus_Clicked(object sender, ButtonReleaseEventArgs args)
-        {
-            _emulationContext.EnableDeviceVsync = !_emulationContext.EnableDeviceVsync;
-
-            Logger.Info?.Print(LogClass.Application, $"VSync toggled to: {_emulationContext.EnableDeviceVsync}");
-        }
-
-        private void DockedMode_Clicked(object sender, ButtonReleaseEventArgs args)
-        {
-            ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
-        }
-
-        private static string GetVolumeLabelText(float volume)
-        {
-            string icon = volume == 0 ? "🔇" : "🔊";
-
-            return $"{icon} {(int)(volume * 100)}%";
-        }
-
-        private void VolumeStatus_Clicked(object sender, ButtonReleaseEventArgs args)
-        {
-            if (_emulationContext != null)
-            {
-                if (_emulationContext.IsAudioMuted())
-                {
-                    _emulationContext.SetVolume(ConfigurationState.Instance.System.AudioVolume);
-                }
-                else
-                {
-                    _emulationContext.SetVolume(0);
-                }
-            }
-        }
-
-        private void AspectRatio_Clicked(object sender, ButtonReleaseEventArgs args)
-        {
-            AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
-
-            ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames<AspectRatio>().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
-        }
-
-        private void Row_Clicked(object sender, ButtonReleaseEventArgs args)
-        {
-            if (args.Event.Button != 3 /* Right Click */)
-            {
-                return;
-            }
-
-            _gameTableSelection.GetSelected(out TreeIter treeIter);
-
-            if (treeIter.UserData == IntPtr.Zero)
-            {
-                return;
-            }
-
-            string titleFilePath = _tableStore.GetValue(treeIter, 9).ToString();
-            string titleName = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[0];
-            string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
-
-            BlitStruct<ApplicationControlProperty> controlData = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10);
-
-            _ = new GameTableContextMenu(this, _virtualFileSystem, _accountManager, _libHacHorizonManager.RyujinxClient, titleFilePath, titleName, titleId, controlData);
-        }
-
-        private void Load_Application_File(object sender, EventArgs args)
-        {
-            using FileChooserNative fileChooser = new("Choose the file to open", this, FileChooserAction.Open, "Open", "Cancel");
-
-            FileFilter filter = new()
-            {
-                Name = "Switch Executables",
-            };
-            filter.AddPattern("*.xci");
-            filter.AddPattern("*.nsp");
-            filter.AddPattern("*.pfs0");
-            filter.AddPattern("*.nca");
-            filter.AddPattern("*.nro");
-            filter.AddPattern("*.nso");
-
-            fileChooser.AddFilter(filter);
-
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                RunApplication(fileChooser.Filename);
-            }
-        }
-
-        private void Load_Application_Folder(object sender, EventArgs args)
-        {
-            using FileChooserNative fileChooser = new("Choose the folder to open", this, FileChooserAction.SelectFolder, "Open", "Cancel");
-
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                RunApplication(fileChooser.Filename);
-            }
-        }
-
-        private void FileMenu_StateChanged(object o, StateChangedArgs args)
-        {
-            _appletMenu.Sensitive = _emulationContext == null && _contentManager.GetCurrentFirmwareVersion() != null && _contentManager.GetCurrentFirmwareVersion().Major > 3;
-            _loadApplicationFile.Sensitive = _emulationContext == null;
-            _loadApplicationFolder.Sensitive = _emulationContext == null;
-        }
-
-        private void Load_Mii_Edit_Applet(object sender, EventArgs args)
-        {
-            string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
-
-            RunApplication(contentPath);
-        }
-
-        private void Open_Ryu_Folder(object sender, EventArgs args)
-        {
-            OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
-        }
-
-        private void OpenLogsFolder_Pressed(object sender, EventArgs args)
-        {
-            string logPath = AppDataManager.GetOrCreateLogsDir();
-            if (!string.IsNullOrEmpty(logPath))
-            {
-                OpenHelper.OpenFolder(logPath);
-            }
-        }
-
-        private void Exit_Pressed(object sender, EventArgs args)
-        {
-            if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
-            {
-                SaveWindowSizePosition();
-                End();
-            }
-        }
-
-        private void Window_Close(object sender, DeleteEventArgs args)
-        {
-            if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
-            {
-                SaveWindowSizePosition();
-                End();
-            }
-            else
-            {
-                args.RetVal = true;
-            }
-        }
-
-        private void SetWindowSizePosition()
-        {
-            DefaultWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth;
-            DefaultHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight;
-
-            Move(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY);
-
-            if (ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized)
-            {
-                Maximize();
-            }
-        }
-
-        private void SaveWindowSizePosition()
-        {
-            GetSize(out int windowWidth, out int windowHeight);
-            GetPosition(out int windowXPos, out int windowYPos);
-
-            ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value = IsMaximized;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth.Value = windowWidth;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight.Value = windowHeight;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX.Value = windowXPos;
-            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY.Value = windowYPos;
-
-            SaveConfig();
-        }
-
-        private void StopEmulation_Pressed(object sender, EventArgs args)
-        {
-            if (_emulationContext != null)
-            {
-                UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
-            }
-
-            _pauseEmulation.Sensitive = false;
-            _resumeEmulation.Sensitive = false;
-            UpdateMenuItem.Sensitive = true;
-            RendererWidget?.Exit();
-        }
-
-        private void PauseEmulation_Pressed(object sender, EventArgs args)
-        {
-            _pauseEmulation.Sensitive = false;
-            _resumeEmulation.Sensitive = true;
-            _emulationContext.System.TogglePauseEmulation(true);
-            Title = TitleHelper.ActiveApplicationTitle(_emulationContext.Processes.ActiveApplication, Program.Version, "Paused");
-            Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
-        }
-
-        private void ResumeEmulation_Pressed(object sender, EventArgs args)
-        {
-            _pauseEmulation.Sensitive = true;
-            _resumeEmulation.Sensitive = false;
-            _emulationContext.System.TogglePauseEmulation(false);
-            Title = TitleHelper.ActiveApplicationTitle(_emulationContext.Processes.ActiveApplication, Program.Version);
-            Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
-        }
-
-        public void ActivatePauseMenu()
-        {
-            _pauseEmulation.Sensitive = true;
-            _resumeEmulation.Sensitive = false;
-        }
-
-        public void TogglePause()
-        {
-            _pauseEmulation.Sensitive ^= true;
-            _resumeEmulation.Sensitive ^= true;
-            _emulationContext.System.TogglePauseEmulation(_resumeEmulation.Sensitive);
-        }
-
-        private void Installer_File_Pressed(object o, EventArgs args)
-        {
-            FileChooserNative fileChooser = new("Choose the firmware file to open", this, FileChooserAction.Open, "Open", "Cancel");
-
-            FileFilter filter = new()
-            {
-                Name = "Switch Firmware Files",
-            };
-            filter.AddPattern("*.zip");
-            filter.AddPattern("*.xci");
-
-            fileChooser.AddFilter(filter);
-
-            HandleInstallerDialog(fileChooser);
-        }
-
-        private void Installer_Directory_Pressed(object o, EventArgs args)
-        {
-            FileChooserNative directoryChooser = new("Choose the firmware directory to open", this, FileChooserAction.SelectFolder, "Open", "Cancel");
-
-            HandleInstallerDialog(directoryChooser);
-        }
-
-        private void HandleInstallerDialog(FileChooserNative fileChooser)
-        {
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                try
-                {
-                    string filename = fileChooser.Filename;
-
-                    fileChooser.Dispose();
-
-                    SystemVersion firmwareVersion = _contentManager.VerifyFirmwarePackage(filename);
-
-                    if (firmwareVersion is null)
-                    {
-                        GtkDialog.CreateErrorDialog($"A valid system firmware was not found in {filename}.");
-
-                        return;
-                    }
-
-                    string dialogTitle = $"Install Firmware {firmwareVersion.VersionString}";
-
-                    SystemVersion currentVersion = _contentManager.GetCurrentFirmwareVersion();
-
-                    string dialogMessage = $"System version {firmwareVersion.VersionString} will be installed.";
-
-                    if (currentVersion != null)
-                    {
-                        dialogMessage += $"\n\nThis will replace the current system version {currentVersion.VersionString}. ";
-                    }
-
-                    dialogMessage += "\n\nDo you want to continue?";
-
-                    ResponseType responseInstallDialog = (ResponseType)GtkDialog.CreateConfirmationDialog(dialogTitle, dialogMessage).Run();
-
-                    MessageDialog waitingDialog = GtkDialog.CreateWaitingDialog(dialogTitle, "Installing firmware...");
-
-                    if (responseInstallDialog == ResponseType.Yes)
-                    {
-                        Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
-
-                        Thread thread = new(() =>
-                        {
-                            Application.Invoke(delegate
-                            {
-                                waitingDialog.Run();
-
-                            });
-
-                            try
-                            {
-                                _contentManager.InstallFirmware(filename);
-
-                                Application.Invoke(delegate
-                                {
-                                    waitingDialog.Dispose();
-
-                                    string message = $"System version {firmwareVersion.VersionString} successfully installed.";
-
-                                    GtkDialog.CreateInfoDialog(dialogTitle, message);
-                                    Logger.Info?.Print(LogClass.Application, message);
-
-                                    // Purge Applet Cache.
-
-                                    DirectoryInfo miiEditorCacheFolder = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
-
-                                    if (miiEditorCacheFolder.Exists)
-                                    {
-                                        miiEditorCacheFolder.Delete(true);
-                                    }
-                                });
-                            }
-                            catch (Exception ex)
-                            {
-                                Application.Invoke(delegate
-                                {
-                                    waitingDialog.Dispose();
-
-                                    GtkDialog.CreateErrorDialog(ex.Message);
-                                });
-                            }
-                            finally
-                            {
-                                RefreshFirmwareLabel();
-                            }
-                        })
-                        {
-                            Name = "GUI.FirmwareInstallerThread",
-                        };
-                        thread.Start();
-                    }
-                }
-                catch (MissingKeyException ex)
-                {
-                    Logger.Error?.Print(LogClass.Application, ex.ToString());
-                    UserErrorDialog.CreateUserErrorDialog(UserError.FirmwareParsingFailed);
-                }
-                catch (Exception ex)
-                {
-                    GtkDialog.CreateErrorDialog(ex.Message);
-                }
-            }
-            else
-            {
-                fileChooser.Dispose();
-            }
-        }
-
-        private void RefreshFirmwareLabel()
-        {
-            SystemVersion currentFirmware = _contentManager.GetCurrentFirmwareVersion();
-
-            Application.Invoke(delegate
-            {
-                _firmwareVersionLabel.Text = currentFirmware != null ? currentFirmware.VersionString : "0.0.0";
-            });
-        }
-
-        private void InstallFileTypes_Pressed(object sender, EventArgs e)
-        {
-            if (FileAssociationHelper.Install())
-            {
-                GtkDialog.CreateInfoDialog("Install file types", "File types successfully installed!");
-            }
-            else
-            {
-                GtkDialog.CreateErrorDialog("Failed to install file types.");
-            }
-        }
-
-        private void UninstallFileTypes_Pressed(object sender, EventArgs e)
-        {
-            if (FileAssociationHelper.Uninstall())
-            {
-                GtkDialog.CreateInfoDialog("Uninstall file types", "File types successfully uninstalled!");
-            }
-            else
-            {
-                GtkDialog.CreateErrorDialog("Failed to uninstall file types.");
-            }
-        }
-
-        private void HandleRelaunch()
-        {
-            if (_userChannelPersistence.PreviousIndex != -1 && _userChannelPersistence.ShouldRestart)
-            {
-                _userChannelPersistence.ShouldRestart = false;
-
-                RunApplication(_currentEmulatedGamePath);
-            }
-            else
-            {
-                // otherwise, clear state.
-                _userChannelPersistence = new UserChannelPersistence();
-                _currentEmulatedGamePath = null;
-                _actionMenu.Sensitive = false;
-                _firmwareInstallFile.Sensitive = true;
-                _firmwareInstallDirectory.Sensitive = true;
-            }
-        }
-
-        private void FullScreen_Toggled(object sender, EventArgs args)
-        {
-            if (!Window.State.HasFlag(Gdk.WindowState.Fullscreen))
-            {
-                Fullscreen();
-
-                ToggleExtraWidgets(false);
-            }
-            else
-            {
-                Unfullscreen();
-
-                ToggleExtraWidgets(true);
-            }
-        }
-
-        private void StartFullScreen_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.StartFullscreen.Value = _startFullScreen.Active;
-
-            SaveConfig();
-        }
-
-        private void ShowConsole_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShowConsole.Value = _showConsole.Active;
-
-            SaveConfig();
-        }
-
-        private void OptionMenu_StateChanged(object o, StateChangedArgs args)
-        {
-            _manageUserProfiles.Sensitive = _emulationContext == null;
-        }
-
-        private void Settings_Pressed(object sender, EventArgs args)
-        {
-            SettingsWindow settingsWindow = new(this, _virtualFileSystem, _contentManager);
-
-            settingsWindow.SetSizeRequest((int)(settingsWindow.DefaultWidth * Program.WindowScaleFactor), (int)(settingsWindow.DefaultHeight * Program.WindowScaleFactor));
-            settingsWindow.Show();
-        }
-
-        private void HideUi_Pressed(object sender, EventArgs args)
-        {
-            ToggleExtraWidgets(false);
-        }
-
-        private void ManageCheats_Pressed(object sender, EventArgs args)
-        {
-            var window = new CheatWindow(
-                _virtualFileSystem,
-                _emulationContext.Processes.ActiveApplication.ProgramId,
-                _emulationContext.Processes.ActiveApplication.ApplicationControlProperties
-                    .Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString(),
-                _currentEmulatedGamePath);
-
-            window.Destroyed += CheatWindow_Destroyed;
-            window.Show();
-        }
-
-        private void CheatWindow_Destroyed(object sender, EventArgs e)
-        {
-            _emulationContext.EnableCheats();
-            (sender as CheatWindow).Destroyed -= CheatWindow_Destroyed;
-        }
-
-        private void ManageUserProfiles_Pressed(object sender, EventArgs args)
-        {
-            UserProfilesManagerWindow userProfilesManagerWindow = new(_accountManager, _contentManager, _virtualFileSystem);
-
-            userProfilesManagerWindow.SetSizeRequest((int)(userProfilesManagerWindow.DefaultWidth * Program.WindowScaleFactor), (int)(userProfilesManagerWindow.DefaultHeight * Program.WindowScaleFactor));
-            userProfilesManagerWindow.Show();
-        }
-
-        private void Simulate_WakeUp_Message_Pressed(object sender, EventArgs args)
-        {
-            _emulationContext?.System.SimulateWakeUpMessage();
-        }
-
-        private void ActionMenu_StateChanged(object o, StateChangedArgs args)
-        {
-            _scanAmiibo.Sensitive = _emulationContext != null && _emulationContext.System.SearchingForAmiibo(out int _);
-            _takeScreenshot.Sensitive = _emulationContext != null;
-        }
-
-        private void Scan_Amiibo(object sender, EventArgs args)
-        {
-            if (_emulationContext.System.SearchingForAmiibo(out int deviceId))
-            {
-                AmiiboWindow amiiboWindow = new()
-                {
-                    LastScannedAmiiboShowAll = _lastScannedAmiiboShowAll,
-                    LastScannedAmiiboId = _lastScannedAmiiboId,
-                    DeviceId = deviceId,
-                    TitleId = _emulationContext.Processes.ActiveApplication.ProgramIdText.ToUpper(),
-                };
-
-                amiiboWindow.DeleteEvent += AmiiboWindow_DeleteEvent;
-
-                amiiboWindow.Show();
-            }
-            else
-            {
-                GtkDialog.CreateInfoDialog($"Amiibo", "The game is currently not ready to receive Amiibo scan data. Ensure that you have an Amiibo-compatible game open and ready to receive Amiibo scan data.");
-            }
-        }
-
-        private void Take_Screenshot(object sender, EventArgs args)
-        {
-            if (_emulationContext != null && RendererWidget != null)
-            {
-                RendererWidget.ScreenshotRequested = true;
-            }
-        }
-
-        private void AmiiboWindow_DeleteEvent(object sender, DeleteEventArgs args)
-        {
-            if (((AmiiboWindow)sender).AmiiboId != "" && ((AmiiboWindow)sender).Response == ResponseType.Ok)
-            {
-                _lastScannedAmiiboId = ((AmiiboWindow)sender).AmiiboId;
-                _lastScannedAmiiboShowAll = ((AmiiboWindow)sender).LastScannedAmiiboShowAll;
-
-                _emulationContext.System.ScanAmiibo(((AmiiboWindow)sender).DeviceId, ((AmiiboWindow)sender).AmiiboId, ((AmiiboWindow)sender).UseRandomUuid);
-            }
-        }
-
-        private void Update_Pressed(object sender, EventArgs args)
-        {
-            if (Updater.CanUpdate(true))
-            {
-                Updater.BeginParse(this, true).ContinueWith(task =>
-                {
-                    Logger.Error?.Print(LogClass.Application, $"Updater error: {task.Exception}");
-                }, TaskContinuationOptions.OnlyOnFaulted);
-            }
-        }
-
-        private void About_Pressed(object sender, EventArgs args)
-        {
-            AboutWindow aboutWindow = new();
-
-            aboutWindow.SetSizeRequest((int)(aboutWindow.DefaultWidth * Program.WindowScaleFactor), (int)(aboutWindow.DefaultHeight * Program.WindowScaleFactor));
-            aboutWindow.Show();
-        }
-
-        private void Fav_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.FavColumn.Value = _favToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void Icon_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.IconColumn.Value = _iconToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void App_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.AppColumn.Value = _appToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void Developer_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.DevColumn.Value = _developerToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void Version_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.VersionColumn.Value = _versionToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void TimePlayed_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn.Value = _timePlayedToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void LastPlayed_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn.Value = _lastPlayedToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void FileExt_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn.Value = _fileExtToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void FileSize_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn.Value = _fileSizeToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void Path_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.GuiColumns.PathColumn.Value = _pathToggle.Active;
-
-            SaveConfig();
-            UpdateColumns();
-        }
-
-        private void NSP_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = _nspShown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void PFS0_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = _pfs0Shown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void XCI_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = _xciShown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void NCA_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value = _ncaShown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void NRO_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = _nroShown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void NSO_Shown_Toggled(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = _nsoShown.Active;
-
-            SaveConfig();
-            UpdateGameTable();
-        }
-
-        private void RefreshList_Pressed(object sender, ButtonReleaseEventArgs args)
-        {
-            UpdateGameTable();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/MainWindow.glade b/src/Ryujinx/Ui/MainWindow.glade
deleted file mode 100644
index 58d5d955..00000000
--- a/src/Ryujinx/Ui/MainWindow.glade
+++ /dev/null
@@ -1,1006 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.40.0 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkApplicationWindow" id="_mainWin">
-    <property name="can-focus">False</property>
-    <property name="title" translatable="yes">Ryujinx</property>
-    <property name="window-position">center</property>
-    <child>
-      <object class="GtkBox" id="_box">
-        <property name="visible">True</property>
-        <property name="can-focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkMenuBar" id="_menuBar">
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <child>
-              <object class="GtkMenuItem" id="_fileMenu">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="label" translatable="yes">File</property>
-                <property name="use-underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkMenuItem" id="_loadApplicationFile">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open a file explorer to choose a Switch compatible file to load</property>
-                        <property name="label" translatable="yes">Load Application from File</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Load_Application_File" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_loadApplicationFolder">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open a file explorer to choose a Switch compatible, unpacked application to load</property>
-                        <property name="label" translatable="yes">Load Unpacked Game</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Load_Application_Folder" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_appletMenu">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Load Applet</property>
-                        <property name="use-underline">True</property>
-                        <child type="submenu">
-                          <object class="GtkMenu">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <child>
-                              <object class="GtkMenuItem" id="LoadMiiEditApplet">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Open Mii Editor Applet in Standalone mode</property>
-                                <property name="label" translatable="yes">Mii Editor</property>
-                                <property name="use-underline">True</property>
-                                <signal name="activate" handler="Load_Mii_Edit_Applet" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="OpenRyuFolder">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open Ryujinx filesystem folder</property>
-                        <property name="label" translatable="yes">Open Ryujinx Folder</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Open_Ryu_Folder" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="OpenLogsFolder">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Opens the folder where logs are written to.</property>
-                        <property name="label" translatable="yes">Open Logs Folder</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="OpenLogsFolder_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="ExitMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Exit Ryujinx</property>
-                        <property name="label" translatable="yes">Exit</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Exit_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="_optionMenu">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="label" translatable="yes">Options</property>
-                <property name="use-underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkMenuItem" id="_fullScreen">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Enter Fullscreen</property>
-                        <property name="use-underline">True</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkCheckMenuItem" id="_startFullScreen">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Start Games in Fullscreen Mode</property>
-                        <property name="use-underline">True</property>
-                        <signal name="toggled" handler="StartFullScreen_Toggled" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkCheckMenuItem" id="_showConsole">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Show Log Console</property>
-                        <property name="use-underline">True</property>
-                        <signal name="toggled" handler="ShowConsole_Toggled" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="GUIColumns">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Select which GUI columns to enable</property>
-                        <property name="label" translatable="yes">Enable GUI Columns</property>
-                        <property name="use-underline">True</property>
-                        <child type="submenu">
-                          <object class="GtkMenu">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_favToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Favorite Games Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Favorite Games Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_iconToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Icon Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Icon Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_appToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Title Name/ID Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Title Name/ID Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_developerToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Developer Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Developer Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_versionToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Version Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Version Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_timePlayedToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Time Played Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Time Played Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_lastPlayedToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Last Played Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Last Played Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_fileExtToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable file extension column in the game list</property>
-                                <property name="label" translatable="yes">Enable File Ext Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_fileSizeToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable File Size Column in the game list</property>
-                                <property name="label" translatable="yes">Enable File Size Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_pathToggle">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Enable or Disable Path Column in the game list</property>
-                                <property name="label" translatable="yes">Enable Path Column</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="ShownFileTypes">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Select which file types to show</property>
-                        <property name="label" translatable="yes">Show File Types</property>
-                        <property name="use-underline">True</property>
-                        <child type="submenu">
-                          <object class="GtkMenu">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_nspShown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .NSP files in the games list</property>
-                                <property name="label" translatable="yes">.NSP</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_pfs0Shown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .PFS0 files in the games list</property>
-                                <property name="label" translatable="yes">.PFS0</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_xciShown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .XCI files in the games list</property>
-                                <property name="label" translatable="yes">.XCI</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_ncaShown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .NCA files in the games list</property>
-                                <property name="label" translatable="yes">.NCA</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_nroShown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .NRO files in the games list</property>
-                                <property name="label" translatable="yes">.NRO</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkCheckMenuItem" id="_nsoShown">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Shows .NSO files in the games list</property>
-                                <property name="label" translatable="yes">.NSO</property>
-                                <property name="use-underline">True</property>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="SettingsMenu">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open settings window</property>
-                        <property name="label" translatable="yes">Settings</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Settings_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_manageUserProfiles">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open User Profiles Manager window</property>
-                        <property name="label" translatable="yes">Manage User Profiles</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="ManageUserProfiles_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="_actionMenu">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="label" translatable="yes">Actions</property>
-                <property name="use-underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkMenuItem" id="_pauseEmulation">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Pause emulation</property>
-                        <property name="label" translatable="yes">Pause Emulation</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="PauseEmulation_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_resumeEmulation">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Resume emulation</property>
-                        <property name="label" translatable="yes">Resume Emulation</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="ResumeEmulation_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_stopEmulation">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Stop emulation of the current game and return to game selection</property>
-                        <property name="label" translatable="yes">Stop Emulation</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="StopEmulation_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_simulateWakeUpMessage">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Simulate a Wake-up Message</property>
-                        <property name="label" translatable="yes">Simulate Wake-up Message</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Simulate_WakeUp_Message_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_scanAmiibo">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Scan an Amiibo</property>
-                        <property name="label" translatable="yes">Scan an Amiibo</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Scan_Amiibo" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_takeScreenshot">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Take a screenshot</property>
-                        <property name="label" translatable="yes">Take Screenshot</property>
-                        <signal name="activate" handler="Take_Screenshot" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_hideUi">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Hide UI (SHOWUIKEY to show)</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="HideUi_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_manageCheats">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Manage Cheats</property>
-                        <signal name="activate" handler="ManageCheats_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="_toolsMenu">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="label" translatable="yes">Tools</property>
-                <property name="use-underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkMenuItem" id="FirmwareSubMenu">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Install Firmware</property>
-                        <property name="use-underline">True</property>
-                        <child type="submenu">
-                          <object class="GtkMenu">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <child>
-                              <object class="GtkMenuItem" id="_firmwareInstallFile">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="label" translatable="yes">Install a firmware from XCI or ZIP</property>
-                                <property name="use-underline">True</property>
-                                <signal name="activate" handler="Installer_File_Pressed" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="_firmwareInstallDirectory">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="label" translatable="yes">Install a firmware from a directory</property>
-                                <property name="use-underline">True</property>
-                                <signal name="activate" handler="Installer_Directory_Pressed" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="_fileTypesSubMenu">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Manage file types</property>
-                        <property name="use-underline">True</property>
-                        <child type="submenu">
-                          <object class="GtkMenu">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <child>
-                              <object class="GtkMenuItem" id="_installFileTypes">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="label" translatable="yes">Install file types</property>
-                                <signal name="activate" handler="InstallFileTypes_Pressed" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="_uninstallFileTypes">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="label" translatable="yes">Uninstall file types</property>
-                                <signal name="activate" handler="UninstallFileTypes_Pressed" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="HelpMenu">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="label" translatable="yes">Help</property>
-                <property name="use-underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkMenuItem" id="UpdateMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Check for updates to Ryujinx</property>
-                        <property name="label" translatable="yes">Check for Updates</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="Update_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkMenuItem" id="About">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="tooltip-text" translatable="yes">Open about window</property>
-                        <property name="label" translatable="yes">About</property>
-                        <property name="use-underline">True</property>
-                        <signal name="activate" handler="About_Pressed" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="_mainBox">
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkBox" id="_viewBox">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="_gameTableWindow">
-                    <property name="visible">True</property>
-                    <property name="can-focus">True</property>
-                    <property name="shadow-type">in</property>
-                    <child>
-                      <object class="GtkTreeView" id="_gameTable">
-                        <property name="visible">True</property>
-                        <property name="can-focus">True</property>
-                        <property name="reorderable">True</property>
-                        <property name="hover-selection">True</property>
-                        <signal name="row-activated" handler="Row_Activated" swapped="no"/>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection" id="_gameTableSelection"/>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="_footerBox">
-                <property name="height-request">19</property>
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <child>
-                  <object class="GtkBox" id="_listStatusBox">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkEventBox">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <signal name="button-release-event" handler="RefreshList_Pressed" swapped="no"/>
-                        <child>
-                          <object class="GtkImage">
-                            <property name="name">RefreshList</property>
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="stock">gtk-refresh</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_progressLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">10</property>
-                        <property name="margin-right">5</property>
-                        <property name="margin-top">2</property>
-                        <property name="margin-bottom">2</property>
-                        <property name="label" translatable="yes">0/0 Games Loaded</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkProgressBar" id="_progressBar">
-                        <property name="width-request">200</property>
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin-left">10</property>
-                        <property name="margin-right">5</property>
-                        <property name="margin-bottom">6</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="_statusBar">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <child>
-                      <object class="GtkEventBox">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <signal name="button-release-event" handler="VSyncStatus_Clicked" swapped="no"/>
-                        <child>
-                          <object class="GtkLabel" id="_vSyncStatus">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="halign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="label" translatable="yes">VSync</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEventBox">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <signal name="button-release-event" handler="DockedMode_Clicked" swapped="no"/>
-                        <child>
-                          <object class="GtkLabel" id="_dockedMode">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="halign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEventBox">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <signal name="button-release-event" handler="VolumeStatus_Clicked" swapped="no"/>
-                        <child>
-                          <object class="GtkLabel" id="_volumeStatus">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="halign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEventBox">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <signal name="button-release-event" handler="AspectRatio_Clicked" swapped="no"/>
-                        <child>
-                          <object class="GtkLabel" id="_aspectRatio">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="halign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">6</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_gameStatus">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">5</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">8</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">9</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_fifoStatus">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">5</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">10</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">11</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_gpuBackend">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">5</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">12</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">13</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_gpuName">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">5</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">14</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <property name="margin-left">5</property>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">System Version</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="_firmwareVersionLabel">
-                        <property name="width-request">50</property>
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">5</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="pack-type">end</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="pack-type">end</property>
-                    <property name="position">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="_loadingStatusLabel">
-                    <property name="can-focus">False</property>
-                    <property name="margin-left">5</property>
-                    <property name="margin-right">5</property>
-                    <property name="label" translatable="yes">0/0 </property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">11</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkProgressBar" id="_loadingStatusBar">
-                    <property name="width-request">200</property>
-                    <property name="can-focus">False</property>
-                    <property name="margin-left">5</property>
-                    <property name="margin-right">5</property>
-                    <property name="margin-bottom">6</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">12</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/OpenGLRenderer.cs b/src/Ryujinx/Ui/OpenGLRenderer.cs
deleted file mode 100644
index d10445b0..00000000
--- a/src/Ryujinx/Ui/OpenGLRenderer.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-using OpenTK.Graphics.OpenGL;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.Input.HLE;
-using SPB.Graphics;
-using SPB.Graphics.Exceptions;
-using SPB.Graphics.OpenGL;
-using SPB.Platform;
-using SPB.Platform.GLX;
-using SPB.Platform.WGL;
-using SPB.Windowing;
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Ui
-{
-    public partial class OpenGLRenderer : RendererWidgetBase
-    {
-        private readonly GraphicsDebugLevel _glLogLevel;
-
-        private bool _initializedOpenGL;
-
-        private OpenGLContextBase _openGLContext;
-        private SwappableNativeWindowBase _nativeWindow;
-
-        public OpenGLRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel)
-        {
-            _glLogLevel = glLogLevel;
-        }
-
-        protected override bool OnDrawn(Cairo.Context cr)
-        {
-            if (!_initializedOpenGL)
-            {
-                IntializeOpenGL();
-            }
-
-            return true;
-        }
-
-        private void IntializeOpenGL()
-        {
-            _nativeWindow = RetrieveNativeWindow();
-
-            Window.EnsureNative();
-
-            _openGLContext = PlatformHelper.CreateOpenGLContext(GetGraphicsMode(), 3, 3, _glLogLevel == GraphicsDebugLevel.None ? OpenGLContextFlags.Compat : OpenGLContextFlags.Compat | OpenGLContextFlags.Debug);
-            _openGLContext.Initialize(_nativeWindow);
-            _openGLContext.MakeCurrent(_nativeWindow);
-
-            // Release the GL exclusivity that SPB gave us as we aren't going to use it in GTK Thread.
-            _openGLContext.MakeCurrent(null);
-
-            WaitEvent.Set();
-
-            _initializedOpenGL = true;
-        }
-
-        private SwappableNativeWindowBase RetrieveNativeWindow()
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);
-
-                return new WGLWindow(new NativeHandle(windowHandle));
-            }
-            else if (OperatingSystem.IsLinux())
-            {
-                IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
-                IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
-
-                return new GLXWindow(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
-            }
-
-            throw new NotImplementedException();
-        }
-
-        [LibraryImport("libgdk-3-0.dll")]
-        private static partial IntPtr gdk_win32_window_get_handle(IntPtr d);
-
-        [LibraryImport("libgdk-3.so.0")]
-        private static partial IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
-
-        [LibraryImport("libgdk-3.so.0")]
-        private static partial IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);
-
-        private static FramebufferFormat GetGraphicsMode()
-        {
-            return Environment.OSVersion.Platform == PlatformID.Unix ? new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false) : FramebufferFormat.Default;
-        }
-
-        public override void InitializeRenderer()
-        {
-            // First take exclusivity on the OpenGL context.
-            ((Graphics.OpenGL.OpenGLRenderer)Renderer).InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(_openGLContext));
-
-            _openGLContext.MakeCurrent(_nativeWindow);
-
-            GL.ClearColor(0, 0, 0, 1.0f);
-            GL.Clear(ClearBufferMask.ColorBufferBit);
-            SwapBuffers();
-        }
-
-        public override void SwapBuffers()
-        {
-            _nativeWindow.SwapBuffers();
-        }
-
-        protected override string GetGpuBackendName()
-        {
-            return "OpenGL";
-        }
-
-        protected override void Dispose(bool disposing)
-        {
-            // Try to bind the OpenGL context before calling the shutdown event.
-            try
-            {
-                _openGLContext?.MakeCurrent(_nativeWindow);
-            }
-            catch (ContextException e)
-            {
-                Logger.Warning?.Print(LogClass.Ui, $"Failed to bind OpenGL context: {e}");
-            }
-
-            Device?.DisposeGpu();
-            NpadManager.Dispose();
-
-            // Unbind context and destroy everything.
-            try
-            {
-                _openGLContext?.MakeCurrent(null);
-            }
-            catch (ContextException e)
-            {
-                Logger.Warning?.Print(LogClass.Ui, $"Failed to unbind OpenGL context: {e}");
-            }
-
-            _openGLContext?.Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/OpenToolkitBindingsContext.cs b/src/Ryujinx/Ui/OpenToolkitBindingsContext.cs
deleted file mode 100644
index 49dd5da8..00000000
--- a/src/Ryujinx/Ui/OpenToolkitBindingsContext.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using SPB.Graphics;
-using System;
-
-namespace Ryujinx.Ui
-{
-    public class OpenToolkitBindingsContext : OpenTK.IBindingsContext
-    {
-        private readonly IBindingsContext _bindingContext;
-
-        public OpenToolkitBindingsContext(IBindingsContext bindingsContext)
-        {
-            _bindingContext = bindingsContext;
-        }
-
-        public IntPtr GetProcAddress(string procName)
-        {
-            return _bindingContext.GetProcAddress(procName);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/RendererWidgetBase.cs b/src/Ryujinx/Ui/RendererWidgetBase.cs
deleted file mode 100644
index 7794e044..00000000
--- a/src/Ryujinx/Ui/RendererWidgetBase.cs
+++ /dev/null
@@ -1,803 +0,0 @@
-using Gdk;
-using Gtk;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.GAL.Multithreading;
-using Ryujinx.Graphics.Gpu;
-using Ryujinx.Input;
-using Ryujinx.Input.GTK3;
-using Ryujinx.Input.HLE;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Widgets;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Image = SixLabors.ImageSharp.Image;
-using Key = Ryujinx.Input.Key;
-using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
-using Switch = Ryujinx.HLE.Switch;
-
-namespace Ryujinx.Ui
-{
-    public abstract class RendererWidgetBase : DrawingArea
-    {
-        private const int SwitchPanelWidth = 1280;
-        private const int SwitchPanelHeight = 720;
-        private const int TargetFps = 60;
-        private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
-        private const float VolumeDelta = 0.05f;
-
-        public ManualResetEvent WaitEvent { get; set; }
-        public NpadManager NpadManager { get; }
-        public TouchScreenManager TouchScreenManager { get; }
-        public Switch Device { get; private set; }
-        public IRenderer Renderer { get; private set; }
-
-        public bool ScreenshotRequested { get; set; }
-        protected int WindowWidth { get; private set; }
-        protected int WindowHeight { get; private set; }
-
-        public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
-
-        private bool _isActive;
-        private bool _isStopped;
-
-        private bool _toggleFullscreen;
-        private bool _toggleDockedMode;
-
-        private readonly long _ticksPerFrame;
-
-        private long _ticks = 0;
-        private float _newVolume;
-
-        private readonly Stopwatch _chrono;
-
-        private KeyboardHotkeyState _prevHotkeyState;
-
-        private readonly ManualResetEvent _exitEvent;
-        private readonly ManualResetEvent _gpuDoneEvent;
-
-        private readonly CancellationTokenSource _gpuCancellationTokenSource;
-
-        // Hide Cursor
-        const int CursorHideIdleTime = 5; // seconds
-        private static readonly Cursor _invisibleCursor = new(Display.Default, CursorType.BlankCursor);
-        private long _lastCursorMoveTime;
-        private HideCursorMode _hideCursorMode;
-        private readonly InputManager _inputManager;
-        private readonly IKeyboard _keyboardInterface;
-        private readonly GraphicsDebugLevel _glLogLevel;
-        private string _gpuBackendName;
-        private string _gpuDriverName;
-        private bool _isMouseInClient;
-
-        public RendererWidgetBase(InputManager inputManager, GraphicsDebugLevel glLogLevel)
-        {
-            var mouseDriver = new GTK3MouseDriver(this);
-
-            _inputManager = inputManager;
-            _inputManager.SetMouseDriver(mouseDriver);
-            NpadManager = _inputManager.CreateNpadManager();
-            TouchScreenManager = _inputManager.CreateTouchScreenManager();
-            _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
-
-            WaitEvent = new ManualResetEvent(false);
-
-            _glLogLevel = glLogLevel;
-
-            Destroyed += Renderer_Destroyed;
-
-            _chrono = new Stopwatch();
-
-            _ticksPerFrame = Stopwatch.Frequency / TargetFps;
-
-            AddEvents((int)(EventMask.ButtonPressMask
-                          | EventMask.ButtonReleaseMask
-                          | EventMask.PointerMotionMask
-                          | EventMask.ScrollMask
-                          | EventMask.EnterNotifyMask
-                          | EventMask.LeaveNotifyMask
-                          | EventMask.KeyPressMask
-                          | EventMask.KeyReleaseMask));
-
-            _exitEvent = new ManualResetEvent(false);
-            _gpuDoneEvent = new ManualResetEvent(false);
-
-            _gpuCancellationTokenSource = new CancellationTokenSource();
-
-            _hideCursorMode = ConfigurationState.Instance.HideCursor;
-            _lastCursorMoveTime = Stopwatch.GetTimestamp();
-
-            ConfigurationState.Instance.HideCursor.Event += HideCursorStateChanged;
-            ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAnriAliasing;
-            ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
-            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
-        }
-
-        private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
-        {
-            Renderer.Window.SetScalingFilter((ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
-            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
-        }
-
-        private void UpdateScalingFilter(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.ScalingFilter> e)
-        {
-            Renderer.Window.SetScalingFilter((ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
-            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
-        }
-
-        public abstract void InitializeRenderer();
-
-        public abstract void SwapBuffers();
-
-        protected abstract string GetGpuBackendName();
-
-        private string GetGpuDriverName()
-        {
-            return Renderer.GetHardwareInfo().GpuDriver;
-        }
-
-        private void HideCursorStateChanged(object sender, ReactiveEventArgs<HideCursorMode> state)
-        {
-            Application.Invoke(delegate
-            {
-                _hideCursorMode = state.NewValue;
-
-                switch (_hideCursorMode)
-                {
-                    case HideCursorMode.Never:
-                        Window.Cursor = null;
-                        break;
-                    case HideCursorMode.OnIdle:
-                        _lastCursorMoveTime = Stopwatch.GetTimestamp();
-                        break;
-                    case HideCursorMode.Always:
-                        Window.Cursor = _invisibleCursor;
-                        break;
-                    default:
-                        throw new ArgumentOutOfRangeException(nameof(state));
-                }
-            });
-        }
-
-        private void Renderer_Destroyed(object sender, EventArgs e)
-        {
-            ConfigurationState.Instance.HideCursor.Event -= HideCursorStateChanged;
-            ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAnriAliasing;
-            ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter;
-            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
-
-            NpadManager.Dispose();
-            Dispose();
-        }
-
-        private void UpdateAnriAliasing(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.AntiAliasing> e)
-        {
-            Renderer?.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue);
-        }
-
-        protected override bool OnMotionNotifyEvent(EventMotion evnt)
-        {
-            if (_hideCursorMode == HideCursorMode.OnIdle)
-            {
-                _lastCursorMoveTime = Stopwatch.GetTimestamp();
-            }
-
-            if (ConfigurationState.Instance.Hid.EnableMouse)
-            {
-                Window.Cursor = _invisibleCursor;
-            }
-
-            _isMouseInClient = true;
-
-            return false;
-        }
-
-        protected override bool OnEnterNotifyEvent(EventCrossing evnt)
-        {
-            Window.Cursor = ConfigurationState.Instance.Hid.EnableMouse ? _invisibleCursor : null;
-
-            _isMouseInClient = true;
-
-            return base.OnEnterNotifyEvent(evnt);
-        }
-
-        protected override bool OnLeaveNotifyEvent(EventCrossing evnt)
-        {
-            Window.Cursor = null;
-
-            _isMouseInClient = false;
-
-            return base.OnLeaveNotifyEvent(evnt);
-        }
-
-        protected override void OnGetPreferredHeight(out int minimumHeight, out int naturalHeight)
-        {
-            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
-
-            // If the monitor is at least 1080p, use the Switch panel size as minimal size.
-            if (monitor.Geometry.Height >= 1080)
-            {
-                minimumHeight = SwitchPanelHeight;
-            }
-            // Otherwise, we default minimal size to 480p 16:9.
-            else
-            {
-                minimumHeight = 480;
-            }
-
-            naturalHeight = minimumHeight;
-        }
-
-        protected override void OnGetPreferredWidth(out int minimumWidth, out int naturalWidth)
-        {
-            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
-
-            // If the monitor is at least 1080p, use the Switch panel size as minimal size.
-            if (monitor.Geometry.Height >= 1080)
-            {
-                minimumWidth = SwitchPanelWidth;
-            }
-            // Otherwise, we default minimal size to 480p 16:9.
-            else
-            {
-                minimumWidth = 854;
-            }
-
-            naturalWidth = minimumWidth;
-        }
-
-        protected override bool OnConfigureEvent(EventConfigure evnt)
-        {
-            bool result = base.OnConfigureEvent(evnt);
-
-            Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
-
-            WindowWidth = evnt.Width * monitor.ScaleFactor;
-            WindowHeight = evnt.Height * monitor.ScaleFactor;
-
-            Renderer?.Window?.SetSize(WindowWidth, WindowHeight);
-
-            return result;
-        }
-
-        private void HandleScreenState(KeyboardStateSnapshot keyboard)
-        {
-            bool toggleFullscreen = keyboard.IsPressed(Key.F11)
-                                || ((keyboard.IsPressed(Key.AltLeft)
-                                || keyboard.IsPressed(Key.AltRight))
-                                && keyboard.IsPressed(Key.Enter))
-                                || keyboard.IsPressed(Key.Escape);
-
-            bool fullScreenToggled = ParentWindow.State.HasFlag(WindowState.Fullscreen);
-
-            if (toggleFullscreen != _toggleFullscreen)
-            {
-                if (toggleFullscreen)
-                {
-                    if (fullScreenToggled)
-                    {
-                        ParentWindow.Unfullscreen();
-                        (Toplevel as MainWindow)?.ToggleExtraWidgets(true);
-                    }
-                    else
-                    {
-                        if (keyboard.IsPressed(Key.Escape))
-                        {
-                            if (!ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
-                            {
-                                Exit();
-                            }
-                        }
-                        else
-                        {
-                            ParentWindow.Fullscreen();
-                            (Toplevel as MainWindow)?.ToggleExtraWidgets(false);
-                        }
-                    }
-                }
-            }
-
-            _toggleFullscreen = toggleFullscreen;
-
-            bool toggleDockedMode = keyboard.IsPressed(Key.F9);
-
-            if (toggleDockedMode != _toggleDockedMode)
-            {
-                if (toggleDockedMode)
-                {
-                    ConfigurationState.Instance.System.EnableDockedMode.Value =
-                        !ConfigurationState.Instance.System.EnableDockedMode.Value;
-                }
-            }
-
-            _toggleDockedMode = toggleDockedMode;
-
-            if (_isMouseInClient)
-            {
-                if (ConfigurationState.Instance.Hid.EnableMouse.Value)
-                {
-                    Window.Cursor = _invisibleCursor;
-                }
-                else
-                {
-                    switch (_hideCursorMode)
-                    {
-                        case HideCursorMode.OnIdle:
-                            long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
-                            Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
-                            break;
-                        case HideCursorMode.Always:
-                            Window.Cursor = _invisibleCursor;
-                            break;
-                        case HideCursorMode.Never:
-                            Window.Cursor = null;
-                            break;
-                    }
-                }
-            }
-        }
-
-        public void Initialize(Switch device)
-        {
-            Device = device;
-
-            IRenderer renderer = Device.Gpu.Renderer;
-
-            if (renderer is ThreadedRenderer tr)
-            {
-                renderer = tr.BaseRenderer;
-            }
-
-            Renderer = renderer;
-            Renderer?.Window?.SetSize(WindowWidth, WindowHeight);
-
-            if (Renderer != null)
-            {
-                Renderer.ScreenCaptured += Renderer_ScreenCaptured;
-            }
-
-            NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
-            TouchScreenManager.Initialize(device);
-        }
-
-        private unsafe void Renderer_ScreenCaptured(object sender, ScreenCaptureImageInfo e)
-        {
-            if (e.Data.Length > 0 && e.Height > 0 && e.Width > 0)
-            {
-                Task.Run(() =>
-                {
-                    lock (this)
-                    {
-                        var currentTime = DateTime.Now;
-                        string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
-                        string directory = AppDataManager.Mode switch
-                        {
-                            AppDataManager.LaunchMode.Portable or AppDataManager.LaunchMode.Custom => System.IO.Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
-                            _ => System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx"),
-                        };
-
-                        string path = System.IO.Path.Combine(directory, filename);
-
-                        try
-                        {
-                            Directory.CreateDirectory(directory);
-                        }
-                        catch (Exception ex)
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"Failed to create directory at path {directory}. Error : {ex.GetType().Name}", "Screenshot");
-
-                            return;
-                        }
-
-                        Image image = e.IsBgra ? Image.LoadPixelData<Bgra32>(e.Data, e.Width, e.Height)
-                                               : Image.LoadPixelData<Rgba32>(e.Data, e.Width, e.Height);
-
-                        if (e.FlipX)
-                        {
-                            image.Mutate(x => x.Flip(FlipMode.Horizontal));
-                        }
-
-                        if (e.FlipY)
-                        {
-                            image.Mutate(x => x.Flip(FlipMode.Vertical));
-                        }
-
-                        image.SaveAsPng(path, new PngEncoder()
-                        {
-                            ColorType = PngColorType.Rgb,
-                        });
-
-                        image.Dispose();
-
-                        Logger.Notice.Print(LogClass.Application, $"Screenshot saved to {path}", "Screenshot");
-                    }
-                });
-            }
-            else
-            {
-                Logger.Error?.Print(LogClass.Application, $"Screenshot is empty. Size : {e.Data.Length} bytes. Resolution : {e.Width}x{e.Height}", "Screenshot");
-            }
-        }
-
-        public void Render()
-        {
-            Gtk.Window parent = Toplevel as Gtk.Window;
-            parent.Present();
-
-            InitializeRenderer();
-
-            Device.Gpu.Renderer.Initialize(_glLogLevel);
-
-            Renderer.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value);
-            Renderer.Window.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
-            Renderer.Window.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
-
-            _gpuBackendName = GetGpuBackendName();
-            _gpuDriverName = GetGpuDriverName();
-
-            Device.Gpu.Renderer.RunLoop(() =>
-            {
-                Device.Gpu.SetGpuThread();
-                Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
-
-                Renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
-
-                (Toplevel as MainWindow)?.ActivatePauseMenu();
-
-                while (_isActive)
-                {
-                    if (_isStopped)
-                    {
-                        return;
-                    }
-
-                    _ticks += _chrono.ElapsedTicks;
-
-                    _chrono.Restart();
-
-                    if (Device.WaitFifo())
-                    {
-                        Device.Statistics.RecordFifoStart();
-                        Device.ProcessFrame();
-                        Device.Statistics.RecordFifoEnd();
-                    }
-
-                    while (Device.ConsumeFrameAvailable())
-                    {
-                        Device.PresentFrame(SwapBuffers);
-                    }
-
-                    if (_ticks >= _ticksPerFrame)
-                    {
-                        string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? "Docked" : "Handheld";
-                        float scale = GraphicsConfig.ResScale;
-                        if (scale != 1)
-                        {
-                            dockedMode += $" ({scale}x)";
-                        }
-
-                        StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
-                            Device.EnableDeviceVsync,
-                            Device.GetVolume(),
-                            _gpuBackendName,
-                            dockedMode,
-                            ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
-                            $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
-                            $"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
-                            $"GPU: {_gpuDriverName}"));
-
-                        _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
-                    }
-                }
-
-                // Make sure all commands in the run loop are fully executed before leaving the loop.
-                if (Device.Gpu.Renderer is ThreadedRenderer threaded)
-                {
-                    threaded.FlushThreadedCommands();
-                }
-
-                _gpuDoneEvent.Set();
-            });
-        }
-
-        public void Start()
-        {
-            _chrono.Restart();
-
-            _isActive = true;
-
-            Gtk.Window parent = Toplevel as Gtk.Window;
-
-            Application.Invoke(delegate
-            {
-                parent.Present();
-
-                var activeProcess = Device.Processes.ActiveApplication;
-
-                parent.Title = TitleHelper.ActiveApplicationTitle(activeProcess, Program.Version);
-            });
-
-            Thread renderLoopThread = new(Render)
-            {
-                Name = "GUI.RenderLoop",
-            };
-            renderLoopThread.Start();
-
-            Thread nvidiaStutterWorkaround = null;
-            if (Renderer is Graphics.OpenGL.OpenGLRenderer)
-            {
-                nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround)
-                {
-                    Name = "GUI.NvidiaStutterWorkaround",
-                };
-                nvidiaStutterWorkaround.Start();
-            }
-
-            MainLoop();
-
-            // NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
-            // We only need to wait for all commands submitted during the main gpu loop to be processed.
-            _gpuDoneEvent.WaitOne();
-            _gpuDoneEvent.Dispose();
-            nvidiaStutterWorkaround?.Join();
-
-            Exit();
-        }
-
-        public void Exit()
-        {
-            TouchScreenManager?.Dispose();
-            NpadManager?.Dispose();
-
-            if (_isStopped)
-            {
-                return;
-            }
-
-            _gpuCancellationTokenSource.Cancel();
-
-            _isStopped = true;
-
-            if (_isActive)
-            {
-                _isActive = false;
-
-                _exitEvent.WaitOne();
-                _exitEvent.Dispose();
-            }
-        }
-
-        private void NvidiaStutterWorkaround()
-        {
-            while (_isActive)
-            {
-                // When NVIDIA Threaded Optimization is on, the driver will snapshot all threads in the system whenever the application creates any new ones.
-                // The ThreadPool has something called a "GateThread" which terminates itself after some inactivity.
-                // However, it immediately starts up again, since the rules regarding when to terminate and when to start differ.
-                // This creates a new thread every second or so.
-                // The main problem with this is that the thread snapshot can take 70ms, is on the OpenGL thread and will delay rendering any graphics.
-                // This is a little over budget on a frame time of 16ms, so creates a large stutter.
-                // The solution is to keep the ThreadPool active so that it never has a reason to terminate the GateThread.
-
-                // TODO: This should be removed when the issue with the GateThread is resolved.
-
-                ThreadPool.QueueUserWorkItem((state) => { });
-                Thread.Sleep(300);
-            }
-        }
-
-        public void MainLoop()
-        {
-            while (_isActive)
-            {
-                UpdateFrame();
-
-                // Polling becomes expensive if it's not slept
-                Thread.Sleep(1);
-            }
-
-            _exitEvent.Set();
-        }
-
-        private bool UpdateFrame()
-        {
-            if (!_isActive)
-            {
-                return true;
-            }
-
-            if (_isStopped)
-            {
-                return false;
-            }
-
-            if ((Toplevel as MainWindow).IsFocused)
-            {
-                Application.Invoke(delegate
-                {
-                    KeyboardStateSnapshot keyboard = _keyboardInterface.GetKeyboardStateSnapshot();
-
-                    HandleScreenState(keyboard);
-
-                    if (keyboard.IsPressed(Key.Delete))
-                    {
-                        if (!ParentWindow.State.HasFlag(WindowState.Fullscreen))
-                        {
-                            Device.Processes.ActiveApplication.DiskCacheLoadState?.Cancel();
-                        }
-                    }
-                });
-            }
-
-            NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
-
-            if ((Toplevel as MainWindow).IsFocused)
-            {
-                KeyboardHotkeyState currentHotkeyState = GetHotkeyState();
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync))
-                {
-                    Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
-                }
-
-                if ((currentHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot)) || ScreenshotRequested)
-                {
-                    ScreenshotRequested = false;
-
-                    Renderer.Screenshot();
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ShowUi) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ShowUi))
-                {
-                    (Toplevel as MainWindow).ToggleExtraWidgets(true);
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.Pause) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.Pause))
-                {
-                    (Toplevel as MainWindow)?.TogglePause();
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleMute) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleMute))
-                {
-                    if (Device.IsAudioMuted())
-                    {
-                        Device.SetVolume(ConfigurationState.Instance.System.AudioVolume);
-                    }
-                    else
-                    {
-                        Device.SetVolume(0);
-                    }
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleUp) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleUp))
-                {
-                    GraphicsConfig.ResScale = GraphicsConfig.ResScale % MaxResolutionScale + 1;
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleDown) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ResScaleDown))
-                {
-                    GraphicsConfig.ResScale =
-                    (MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.VolumeUp) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.VolumeUp))
-                {
-                    _newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
-                    Device.SetVolume(_newVolume);
-                }
-
-                if (currentHotkeyState.HasFlag(KeyboardHotkeyState.VolumeDown) &&
-                    !_prevHotkeyState.HasFlag(KeyboardHotkeyState.VolumeDown))
-                {
-                    _newVolume = MathF.Round((Device.GetVolume() - VolumeDelta), 2);
-                    Device.SetVolume(_newVolume);
-                }
-
-                _prevHotkeyState = currentHotkeyState;
-            }
-
-            // Touchscreen
-            bool hasTouch = false;
-
-            // Get screen touch position
-            if ((Toplevel as MainWindow).IsFocused && !ConfigurationState.Instance.Hid.EnableMouse)
-            {
-                hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as GTK3MouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
-            }
-
-            if (!hasTouch)
-            {
-                TouchScreenManager.Update(false);
-            }
-
-            Device.Hid.DebugPad.Update();
-
-            return true;
-        }
-
-        [Flags]
-        private enum KeyboardHotkeyState
-        {
-            None = 0,
-            ToggleVSync = 1 << 0,
-            Screenshot = 1 << 1,
-            ShowUi = 1 << 2,
-            Pause = 1 << 3,
-            ToggleMute = 1 << 4,
-            ResScaleUp = 1 << 5,
-            ResScaleDown = 1 << 6,
-            VolumeUp = 1 << 7,
-            VolumeDown = 1 << 8,
-        }
-
-        private KeyboardHotkeyState GetHotkeyState()
-        {
-            KeyboardHotkeyState state = KeyboardHotkeyState.None;
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
-            {
-                state |= KeyboardHotkeyState.ToggleVSync;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
-            {
-                state |= KeyboardHotkeyState.Screenshot;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
-            {
-                state |= KeyboardHotkeyState.ShowUi;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
-            {
-                state |= KeyboardHotkeyState.Pause;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute))
-            {
-                state |= KeyboardHotkeyState.ToggleMute;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp))
-            {
-                state |= KeyboardHotkeyState.ResScaleUp;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown))
-            {
-                state |= KeyboardHotkeyState.ResScaleDown;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
-            {
-                state |= KeyboardHotkeyState.VolumeUp;
-            }
-
-            if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
-            {
-                state |= KeyboardHotkeyState.VolumeDown;
-            }
-
-            return state;
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/SPBOpenGLContext.cs b/src/Ryujinx/Ui/SPBOpenGLContext.cs
deleted file mode 100644
index 0c5e5736..00000000
--- a/src/Ryujinx/Ui/SPBOpenGLContext.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using OpenTK.Graphics.OpenGL;
-using Ryujinx.Graphics.OpenGL;
-using SPB.Graphics;
-using SPB.Graphics.OpenGL;
-using SPB.Platform;
-using SPB.Windowing;
-
-namespace Ryujinx.Ui
-{
-    class SPBOpenGLContext : IOpenGLContext
-    {
-        private readonly OpenGLContextBase _context;
-        private readonly NativeWindowBase _window;
-
-        private SPBOpenGLContext(OpenGLContextBase context, NativeWindowBase window)
-        {
-            _context = context;
-            _window = window;
-        }
-
-        public void Dispose()
-        {
-            _context.Dispose();
-            _window.Dispose();
-        }
-
-        public void MakeCurrent()
-        {
-            _context.MakeCurrent(_window);
-        }
-
-        public bool HasContext() => _context.IsCurrent;
-
-        public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
-        {
-            OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);
-            NativeWindowBase window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100);
-
-            context.Initialize(window);
-            context.MakeCurrent(window);
-
-            GL.LoadBindings(new OpenToolkitBindingsContext(context));
-
-            context.MakeCurrent(null);
-
-            return new SPBOpenGLContext(context, window);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/StatusUpdatedEventArgs.cs b/src/Ryujinx/Ui/StatusUpdatedEventArgs.cs
deleted file mode 100644
index 72e7d7f5..00000000
--- a/src/Ryujinx/Ui/StatusUpdatedEventArgs.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-namespace Ryujinx.Ui
-{
-    public class StatusUpdatedEventArgs : EventArgs
-    {
-        public bool VSyncEnabled;
-        public float Volume;
-        public string DockedMode;
-        public string AspectRatio;
-        public string GameStatus;
-        public string FifoStatus;
-        public string GpuName;
-        public string GpuBackend;
-
-        public StatusUpdatedEventArgs(bool vSyncEnabled, float volume, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName)
-        {
-            VSyncEnabled = vSyncEnabled;
-            Volume = volume;
-            GpuBackend = gpuBackend;
-            DockedMode = dockedMode;
-            AspectRatio = aspectRatio;
-            GameStatus = gameStatus;
-            FifoStatus = fifoStatus;
-            GpuName = gpuName;
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/VulkanRenderer.cs b/src/Ryujinx/Ui/VulkanRenderer.cs
deleted file mode 100644
index e1aae096..00000000
--- a/src/Ryujinx/Ui/VulkanRenderer.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using Gdk;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Input.HLE;
-using Ryujinx.Ui.Helper;
-using SPB.Graphics.Vulkan;
-using SPB.Platform.Metal;
-using SPB.Platform.Win32;
-using SPB.Platform.X11;
-using SPB.Windowing;
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Ui
-{
-    public partial class VulkanRenderer : RendererWidgetBase
-    {
-        public NativeWindowBase NativeWindow { get; private set; }
-        private UpdateBoundsCallbackDelegate _updateBoundsCallback;
-
-        public VulkanRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel) { }
-
-        private NativeWindowBase RetrieveNativeWindow()
-        {
-            if (OperatingSystem.IsWindows())
-            {
-                IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);
-
-                return new SimpleWin32Window(new NativeHandle(windowHandle));
-            }
-            else if (OperatingSystem.IsLinux())
-            {
-                IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
-                IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
-
-                return new SimpleX11Window(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
-            }
-            else if (OperatingSystem.IsMacOS())
-            {
-                IntPtr metalLayer = MetalHelper.GetMetalLayer(Display, Window, out IntPtr nsView, out _updateBoundsCallback);
-
-                return new SimpleMetalWindow(new NativeHandle(nsView), new NativeHandle(metalLayer));
-            }
-
-            throw new NotImplementedException();
-        }
-
-        [LibraryImport("libgdk-3-0.dll")]
-        private static partial IntPtr gdk_win32_window_get_handle(IntPtr d);
-
-        [LibraryImport("libgdk-3.so.0")]
-        private static partial IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
-
-        [LibraryImport("libgdk-3.so.0")]
-        private static partial IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);
-
-        protected override bool OnConfigureEvent(EventConfigure evnt)
-        {
-            if (NativeWindow == null)
-            {
-                NativeWindow = RetrieveNativeWindow();
-
-                WaitEvent.Set();
-            }
-
-            bool result = base.OnConfigureEvent(evnt);
-
-            _updateBoundsCallback?.Invoke(Window);
-
-            return result;
-        }
-
-        public unsafe IntPtr CreateWindowSurface(IntPtr instance)
-        {
-            return VulkanHelper.CreateWindowSurface(instance, NativeWindow);
-        }
-
-        public override void InitializeRenderer() { }
-
-        public override void SwapBuffers() { }
-
-        protected override string GetGpuBackendName()
-        {
-            return "Vulkan";
-        }
-
-        protected override void Dispose(bool disposing)
-        {
-            Device?.DisposeGpu();
-
-            NpadManager.Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.Designer.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.Designer.cs
deleted file mode 100644
index 162c172d..00000000
--- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.Designer.cs
+++ /dev/null
@@ -1,233 +0,0 @@
-using Gtk;
-using System;
-
-namespace Ryujinx.Ui.Widgets
-{
-    public partial class GameTableContextMenu : Menu
-    {
-        private MenuItem _openSaveUserDirMenuItem;
-        private MenuItem _openSaveDeviceDirMenuItem;
-        private MenuItem _openSaveBcatDirMenuItem;
-        private MenuItem _manageTitleUpdatesMenuItem;
-        private MenuItem _manageDlcMenuItem;
-        private MenuItem _manageCheatMenuItem;
-        private MenuItem _openTitleModDirMenuItem;
-        private MenuItem _openTitleSdModDirMenuItem;
-        private Menu _extractSubMenu;
-        private MenuItem _extractMenuItem;
-        private MenuItem _extractRomFsMenuItem;
-        private MenuItem _extractExeFsMenuItem;
-        private MenuItem _extractLogoMenuItem;
-        private Menu _manageSubMenu;
-        private MenuItem _manageCacheMenuItem;
-        private MenuItem _purgePtcCacheMenuItem;
-        private MenuItem _purgeShaderCacheMenuItem;
-        private MenuItem _openPtcDirMenuItem;
-        private MenuItem _openShaderCacheDirMenuItem;
-        private MenuItem _createShortcutMenuItem;
-
-        private void InitializeComponent()
-        {
-            //
-            // _openSaveUserDirMenuItem
-            //
-            _openSaveUserDirMenuItem = new MenuItem("Open User Save Directory")
-            {
-                TooltipText = "Open the directory which contains Application's User Saves.",
-            };
-            _openSaveUserDirMenuItem.Activated += OpenSaveUserDir_Clicked;
-
-            //
-            // _openSaveDeviceDirMenuItem
-            //
-            _openSaveDeviceDirMenuItem = new MenuItem("Open Device Save Directory")
-            {
-                TooltipText = "Open the directory which contains Application's Device Saves.",
-            };
-            _openSaveDeviceDirMenuItem.Activated += OpenSaveDeviceDir_Clicked;
-
-            //
-            // _openSaveBcatDirMenuItem
-            //
-            _openSaveBcatDirMenuItem = new MenuItem("Open BCAT Save Directory")
-            {
-                TooltipText = "Open the directory which contains Application's BCAT Saves.",
-            };
-            _openSaveBcatDirMenuItem.Activated += OpenSaveBcatDir_Clicked;
-
-            //
-            // _manageTitleUpdatesMenuItem
-            //
-            _manageTitleUpdatesMenuItem = new MenuItem("Manage Title Updates")
-            {
-                TooltipText = "Open the Title Update management window",
-            };
-            _manageTitleUpdatesMenuItem.Activated += ManageTitleUpdates_Clicked;
-
-            //
-            // _manageDlcMenuItem
-            //
-            _manageDlcMenuItem = new MenuItem("Manage DLC")
-            {
-                TooltipText = "Open the DLC management window",
-            };
-            _manageDlcMenuItem.Activated += ManageDlc_Clicked;
-
-            //
-            // _manageCheatMenuItem
-            //
-            _manageCheatMenuItem = new MenuItem("Manage Cheats")
-            {
-                TooltipText = "Open the Cheat management window",
-            };
-            _manageCheatMenuItem.Activated += ManageCheats_Clicked;
-
-            //
-            // _openTitleModDirMenuItem
-            //
-            _openTitleModDirMenuItem = new MenuItem("Open Mods Directory")
-            {
-                TooltipText = "Open the directory which contains Application's Mods.",
-            };
-            _openTitleModDirMenuItem.Activated += OpenTitleModDir_Clicked;
-
-            //
-            // _openTitleSdModDirMenuItem
-            //
-            _openTitleSdModDirMenuItem = new MenuItem("Open Atmosphere Mods Directory")
-            {
-                TooltipText = "Open the alternative SD card atmosphere directory which contains the Application's Mods.",
-            };
-            _openTitleSdModDirMenuItem.Activated += OpenTitleSdModDir_Clicked;
-
-            //
-            // _extractSubMenu
-            //
-            _extractSubMenu = new Menu();
-
-            //
-            // _extractMenuItem
-            //
-            _extractMenuItem = new MenuItem("Extract Data")
-            {
-                Submenu = _extractSubMenu
-            };
-
-            //
-            // _extractRomFsMenuItem
-            //
-            _extractRomFsMenuItem = new MenuItem("RomFS")
-            {
-                TooltipText = "Extract the RomFS section from Application's current config (including updates).",
-            };
-            _extractRomFsMenuItem.Activated += ExtractRomFs_Clicked;
-
-            //
-            // _extractExeFsMenuItem
-            //
-            _extractExeFsMenuItem = new MenuItem("ExeFS")
-            {
-                TooltipText = "Extract the ExeFS section from Application's current config (including updates).",
-            };
-            _extractExeFsMenuItem.Activated += ExtractExeFs_Clicked;
-
-            //
-            // _extractLogoMenuItem
-            //
-            _extractLogoMenuItem = new MenuItem("Logo")
-            {
-                TooltipText = "Extract the Logo section from Application's current config (including updates).",
-            };
-            _extractLogoMenuItem.Activated += ExtractLogo_Clicked;
-
-            //
-            // _manageSubMenu
-            //
-            _manageSubMenu = new Menu();
-
-            //
-            // _manageCacheMenuItem
-            //
-            _manageCacheMenuItem = new MenuItem("Cache Management")
-            {
-                Submenu = _manageSubMenu,
-            };
-
-            //
-            // _purgePtcCacheMenuItem
-            //
-            _purgePtcCacheMenuItem = new MenuItem("Queue PPTC Rebuild")
-            {
-                TooltipText = "Trigger PPTC to rebuild at boot time on the next game launch.",
-            };
-            _purgePtcCacheMenuItem.Activated += PurgePtcCache_Clicked;
-
-            //
-            // _purgeShaderCacheMenuItem
-            //
-            _purgeShaderCacheMenuItem = new MenuItem("Purge Shader Cache")
-            {
-                TooltipText = "Delete the Application's shader cache.",
-            };
-            _purgeShaderCacheMenuItem.Activated += PurgeShaderCache_Clicked;
-
-            //
-            // _openPtcDirMenuItem
-            //
-            _openPtcDirMenuItem = new MenuItem("Open PPTC Directory")
-            {
-                TooltipText = "Open the directory which contains the Application's PPTC cache.",
-            };
-            _openPtcDirMenuItem.Activated += OpenPtcDir_Clicked;
-
-            //
-            // _openShaderCacheDirMenuItem
-            //
-            _openShaderCacheDirMenuItem = new MenuItem("Open Shader Cache Directory")
-            {
-                TooltipText = "Open the directory which contains the Application's shader cache.",
-            };
-            _openShaderCacheDirMenuItem.Activated += OpenShaderCacheDir_Clicked;
-
-            //
-            // _createShortcutMenuItem
-            //
-            _createShortcutMenuItem = new MenuItem("Create Application Shortcut")
-            {
-                TooltipText = OperatingSystem.IsMacOS() ? "Create a shortcut in macOS's Applications folder that launches the selected Application" : "Create a Desktop Shortcut that launches the selected Application."
-            };
-            _createShortcutMenuItem.Activated += CreateShortcut_Clicked;
-
-            ShowComponent();
-        }
-
-        private void ShowComponent()
-        {
-            _extractSubMenu.Append(_extractExeFsMenuItem);
-            _extractSubMenu.Append(_extractRomFsMenuItem);
-            _extractSubMenu.Append(_extractLogoMenuItem);
-
-            _manageSubMenu.Append(_purgePtcCacheMenuItem);
-            _manageSubMenu.Append(_purgeShaderCacheMenuItem);
-            _manageSubMenu.Append(_openPtcDirMenuItem);
-            _manageSubMenu.Append(_openShaderCacheDirMenuItem);
-
-            Add(_createShortcutMenuItem);
-            Add(new SeparatorMenuItem());
-            Add(_openSaveUserDirMenuItem);
-            Add(_openSaveDeviceDirMenuItem);
-            Add(_openSaveBcatDirMenuItem);
-            Add(new SeparatorMenuItem());
-            Add(_manageTitleUpdatesMenuItem);
-            Add(_manageDlcMenuItem);
-            Add(_manageCheatMenuItem);
-            Add(_openTitleModDirMenuItem);
-            Add(_openTitleSdModDirMenuItem);
-            Add(new SeparatorMenuItem());
-            Add(_manageCacheMenuItem);
-            Add(_extractMenuItem);
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
deleted file mode 100644
index eb9f52d7..00000000
--- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
+++ /dev/null
@@ -1,644 +0,0 @@
-using Gtk;
-using LibHac;
-using LibHac.Account;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.Fs.Shim;
-using LibHac.FsSystem;
-using LibHac.Ns;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
-using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using Ryujinx.Ui.Windows;
-using System;
-using System.Buffers;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using System.Threading;
-
-namespace Ryujinx.Ui.Widgets
-{
-    public partial class GameTableContextMenu : Menu
-    {
-        private readonly MainWindow _parent;
-        private readonly VirtualFileSystem _virtualFileSystem;
-        private readonly AccountManager _accountManager;
-        private readonly HorizonClient _horizonClient;
-        private readonly BlitStruct<ApplicationControlProperty> _controlData;
-
-        private readonly string _titleFilePath;
-        private readonly string _titleName;
-        private readonly string _titleIdText;
-        private readonly ulong _titleId;
-
-        private MessageDialog _dialog;
-        private bool _cancel;
-
-        public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, AccountManager accountManager, HorizonClient horizonClient, string titleFilePath, string titleName, string titleId, BlitStruct<ApplicationControlProperty> controlData)
-        {
-            _parent = parent;
-
-            InitializeComponent();
-
-            _virtualFileSystem = virtualFileSystem;
-            _accountManager = accountManager;
-            _horizonClient = horizonClient;
-            _titleFilePath = titleFilePath;
-            _titleName = titleName;
-            _titleIdText = titleId;
-            _controlData = controlData;
-
-            if (!ulong.TryParse(_titleIdText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _titleId))
-            {
-                GtkDialog.CreateErrorDialog("The selected game did not have a valid Title Id");
-
-                return;
-            }
-
-            _openSaveUserDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.UserAccountSaveDataSize > 0;
-            _openSaveDeviceDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.DeviceSaveDataSize > 0;
-            _openSaveBcatDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.BcatDeliveryCacheStorageSize > 0;
-
-            string fileExt = System.IO.Path.GetExtension(_titleFilePath).ToLower();
-            bool hasNca = fileExt == ".nca" || fileExt == ".nsp" || fileExt == ".pfs0" || fileExt == ".xci";
-
-            _extractRomFsMenuItem.Sensitive = hasNca;
-            _extractExeFsMenuItem.Sensitive = hasNca;
-            _extractLogoMenuItem.Sensitive = hasNca;
-
-            _createShortcutMenuItem.Sensitive = !ReleaseInformation.IsFlatHubBuild;
-
-            PopupAtPointer(null);
-        }
-
-        private bool TryFindSaveData(string titleName, ulong titleId, BlitStruct<ApplicationControlProperty> controlHolder, in SaveDataFilter filter, out ulong saveDataId)
-        {
-            saveDataId = default;
-
-            Result result = _horizonClient.Fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, in filter);
-
-            if (ResultFs.TargetNotFound.Includes(result))
-            {
-                ref ApplicationControlProperty control = ref controlHolder.Value;
-
-                Logger.Info?.Print(LogClass.Application, $"Creating save directory for Title: {titleName} [{titleId:x16}]");
-
-                if (Utilities.IsZeros(controlHolder.ByteSpan))
-                {
-                    // If the current application doesn't have a loaded control property, create a dummy one
-                    // and set the savedata sizes so a user savedata will be created.
-                    control = ref new BlitStruct<ApplicationControlProperty>(1).Value;
-
-                    // The set sizes don't actually matter as long as they're non-zero because we use directory savedata.
-                    control.UserAccountSaveDataSize = 0x4000;
-                    control.UserAccountSaveDataJournalSize = 0x4000;
-
-                    Logger.Warning?.Print(LogClass.Application, "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
-                }
-
-                Uid user = new((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
-
-                result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user);
-
-                if (result.IsFailure())
-                {
-                    GtkDialog.CreateErrorDialog($"There was an error creating the specified savedata: {result.ToStringWithName()}");
-
-                    return false;
-                }
-
-                // Try to find the savedata again after creating it
-                result = _horizonClient.Fs.FindSaveDataWithFilter(out saveDataInfo, SaveDataSpaceId.User, in filter);
-            }
-
-            if (result.IsSuccess())
-            {
-                saveDataId = saveDataInfo.SaveDataId;
-
-                return true;
-            }
-
-            GtkDialog.CreateErrorDialog($"There was an error finding the specified savedata: {result.ToStringWithName()}");
-
-            return false;
-        }
-
-        private void OpenSaveDir(in SaveDataFilter saveDataFilter)
-        {
-            if (!TryFindSaveData(_titleName, _titleId, _controlData, in saveDataFilter, out ulong saveDataId))
-            {
-                return;
-            }
-
-            string saveRootPath = System.IO.Path.Combine(VirtualFileSystem.GetNandPath(), $"user/save/{saveDataId:x16}");
-
-            if (!Directory.Exists(saveRootPath))
-            {
-                // Inconsistent state. Create the directory
-                Directory.CreateDirectory(saveRootPath);
-            }
-
-            string committedPath = System.IO.Path.Combine(saveRootPath, "0");
-            string workingPath = System.IO.Path.Combine(saveRootPath, "1");
-
-            // If the committed directory exists, that path will be loaded the next time the savedata is mounted
-            if (Directory.Exists(committedPath))
-            {
-                OpenHelper.OpenFolder(committedPath);
-            }
-            else
-            {
-                // If the working directory exists and the committed directory doesn't,
-                // the working directory will be loaded the next time the savedata is mounted
-                if (!Directory.Exists(workingPath))
-                {
-                    Directory.CreateDirectory(workingPath);
-                }
-
-                OpenHelper.OpenFolder(workingPath);
-            }
-        }
-
-        private void ExtractSection(NcaSectionType ncaSectionType, int programIndex = 0)
-        {
-            FileChooserNative fileChooser = new("Choose the folder to extract into", _parent, FileChooserAction.SelectFolder, "Extract", "Cancel");
-
-            ResponseType response = (ResponseType)fileChooser.Run();
-            string destination = fileChooser.Filename;
-
-            fileChooser.Dispose();
-
-            if (response == ResponseType.Accept)
-            {
-                Thread extractorThread = new(() =>
-                {
-                    Gtk.Application.Invoke(delegate
-                    {
-                        _dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Cancel, null)
-                        {
-                            Title = "Ryujinx - NCA Section Extractor",
-                            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"),
-                            SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_titleFilePath)}...",
-                            WindowPosition = WindowPosition.Center,
-                        };
-
-                        int dialogResponse = _dialog.Run();
-                        if (dialogResponse == (int)ResponseType.Cancel || dialogResponse == (int)ResponseType.DeleteEvent)
-                        {
-                            _cancel = true;
-                            _dialog.Dispose();
-                        }
-                    });
-
-                    using FileStream file = new(_titleFilePath, FileMode.Open, FileAccess.Read);
-
-                    Nca mainNca = null;
-                    Nca patchNca = null;
-
-                    if ((System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nsp") ||
-                        (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".pfs0") ||
-                        (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".xci"))
-                    {
-                        IFileSystem pfs;
-
-                        if (System.IO.Path.GetExtension(_titleFilePath) == ".xci")
-                        {
-                            Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
-
-                            pfs = xci.OpenPartition(XciPartitionType.Secure);
-                        }
-                        else
-                        {
-                            var pfsTemp = new PartitionFileSystem();
-                            pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
-                            pfs = pfsTemp;
-                        }
-
-                        foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
-                        {
-                            using var ncaFile = new UniqueRef<IFile>();
-
-                            pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                            Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Release().AsStorage());
-
-                            if (nca.Header.ContentType == NcaContentType.Program)
-                            {
-                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
-
-                                if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
-                                {
-                                    patchNca = nca;
-                                }
-                                else
-                                {
-                                    mainNca = nca;
-                                }
-                            }
-                        }
-                    }
-                    else if (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nca")
-                    {
-                        mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
-                    }
-
-                    if (mainNca == null)
-                    {
-                        Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA is not present in the selected file.");
-
-                        Gtk.Application.Invoke(delegate
-                            {
-                                GtkDialog.CreateErrorDialog("Extraction failure. The main NCA is not present in the selected file.");
-                            });
-
-                        return;
-                    }
-
-                    (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _);
-
-                    if (updatePatchNca != null)
-                    {
-                        patchNca = updatePatchNca;
-                    }
-
-                    int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);
-
-                    bool sectionExistsInPatch = false;
-
-                    if (patchNca != null)
-                    {
-                        sectionExistsInPatch = patchNca.CanOpenSection(index);
-                    }
-
-                    IFileSystem ncaFileSystem = sectionExistsInPatch ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)
-                                                                         : mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);
-
-                    FileSystemClient fsClient = _horizonClient.Fs;
-
-                    string source = DateTime.Now.ToFileTime().ToString()[10..];
-                    string output = DateTime.Now.ToFileTime().ToString()[10..];
-
-                    using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem);
-                    using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination));
-
-                    fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref);
-                    fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref);
-
-                    (Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/");
-
-                    if (!canceled)
-                    {
-                        if (resultCode.Value.IsFailure())
-                        {
-                            Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}");
-
-                            Gtk.Application.Invoke(delegate
-                                {
-                                    _dialog?.Dispose();
-
-                                    GtkDialog.CreateErrorDialog("Extraction failed. Read the log file for further information.");
-                                });
-                        }
-                        else if (resultCode.Value.IsSuccess())
-                        {
-                            Gtk.Application.Invoke(delegate
-                                {
-                                    _dialog?.Dispose();
-
-                                    MessageDialog dialog = new(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
-                                    {
-                                        Title = "Ryujinx - NCA Section Extractor",
-                                        Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"),
-                                        SecondaryText = "Extraction completed successfully.",
-                                        WindowPosition = WindowPosition.Center,
-                                    };
-
-                                    dialog.Run();
-                                    dialog.Dispose();
-                                });
-                        }
-                    }
-
-                    fsClient.Unmount(source.ToU8Span());
-                    fsClient.Unmount(output.ToU8Span());
-                })
-                {
-                    Name = "GUI.NcaSectionExtractorThread",
-                    IsBackground = true,
-                };
-                extractorThread.Start();
-            }
-        }
-
-        private (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath)
-        {
-            Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath.ToU8Span(), OpenDirectoryMode.All);
-            if (rc.IsFailure())
-            {
-                return (rc, false);
-            }
-
-            using (sourceHandle)
-            {
-                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
-                {
-                    if (_cancel)
-                    {
-                        return (null, true);
-                    }
-
-                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
-                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));
-
-                    if (entry.Type == DirectoryEntryType.Directory)
-                    {
-                        fs.EnsureDirectoryExists(subDstPath);
-
-                        (Result? result, bool canceled) = CopyDirectory(fs, subSrcPath, subDstPath);
-                        if (canceled || result.Value.IsFailure())
-                        {
-                            return (result, canceled);
-                        }
-                    }
-
-                    if (entry.Type == DirectoryEntryType.File)
-                    {
-                        fs.CreateOrOverwriteFile(subDstPath, entry.Size);
-
-                        rc = CopyFile(fs, subSrcPath, subDstPath);
-                        if (rc.IsFailure())
-                        {
-                            return (rc, false);
-                        }
-                    }
-                }
-            }
-
-            return (Result.Success, false);
-        }
-
-        public static Result CopyFile(FileSystemClient fs, string sourcePath, string destPath)
-        {
-            Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath.ToU8Span(), OpenMode.Read);
-            if (rc.IsFailure())
-            {
-                return rc;
-            }
-
-            using (sourceHandle)
-            {
-                rc = fs.OpenFile(out FileHandle destHandle, destPath.ToU8Span(), OpenMode.Write | OpenMode.AllowAppend);
-                if (rc.IsFailure())
-                {
-                    return rc;
-                }
-
-                using (destHandle)
-                {
-                    const int MaxBufferSize = 1024 * 1024;
-
-                    rc = fs.GetFileSize(out long fileSize, sourceHandle);
-                    if (rc.IsFailure())
-                    {
-                        return rc;
-                    }
-
-                    int bufferSize = (int)Math.Min(MaxBufferSize, fileSize);
-
-                    byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
-                    try
-                    {
-                        for (long offset = 0; offset < fileSize; offset += bufferSize)
-                        {
-                            int toRead = (int)Math.Min(fileSize - offset, bufferSize);
-                            Span<byte> buf = buffer.AsSpan(0, toRead);
-
-                            rc = fs.ReadFile(out long _, sourceHandle, offset, buf);
-                            if (rc.IsFailure())
-                            {
-                                return rc;
-                            }
-
-                            rc = fs.WriteFile(destHandle, offset, buf, WriteOption.None);
-                            if (rc.IsFailure())
-                            {
-                                return rc;
-                            }
-                        }
-                    }
-                    finally
-                    {
-                        ArrayPool<byte>.Shared.Return(buffer);
-                    }
-
-                    rc = fs.FlushFile(destHandle);
-                    if (rc.IsFailure())
-                    {
-                        return rc;
-                    }
-                }
-            }
-
-            return Result.Success;
-        }
-
-        //
-        // Events
-        //
-        private void OpenSaveUserDir_Clicked(object sender, EventArgs args)
-        {
-            var userId = new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
-            var saveDataFilter = SaveDataFilter.Make(_titleId, saveType: default, userId, saveDataId: default, index: default);
-
-            OpenSaveDir(in saveDataFilter);
-        }
-
-        private void OpenSaveDeviceDir_Clicked(object sender, EventArgs args)
-        {
-            var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Device, userId: default, saveDataId: default, index: default);
-
-            OpenSaveDir(in saveDataFilter);
-        }
-
-        private void OpenSaveBcatDir_Clicked(object sender, EventArgs args)
-        {
-            var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
-
-            OpenSaveDir(in saveDataFilter);
-        }
-
-        private void ManageTitleUpdates_Clicked(object sender, EventArgs args)
-        {
-            new TitleUpdateWindow(_parent, _virtualFileSystem, _titleIdText, _titleName).Show();
-        }
-
-        private void ManageDlc_Clicked(object sender, EventArgs args)
-        {
-            new DlcWindow(_virtualFileSystem, _titleIdText, _titleName).Show();
-        }
-
-        private void ManageCheats_Clicked(object sender, EventArgs args)
-        {
-            new CheatWindow(_virtualFileSystem, _titleId, _titleName, _titleFilePath).Show();
-        }
-
-        private void OpenTitleModDir_Clicked(object sender, EventArgs args)
-        {
-            string modsBasePath = ModLoader.GetModsBasePath();
-            string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, _titleIdText);
-
-            OpenHelper.OpenFolder(titleModsPath);
-        }
-
-        private void OpenTitleSdModDir_Clicked(object sender, EventArgs args)
-        {
-            string sdModsBasePath = ModLoader.GetSdModsBasePath();
-            string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, _titleIdText);
-
-            OpenHelper.OpenFolder(titleModsPath);
-        }
-
-        private void ExtractRomFs_Clicked(object sender, EventArgs args)
-        {
-            ExtractSection(NcaSectionType.Data);
-        }
-
-        private void ExtractExeFs_Clicked(object sender, EventArgs args)
-        {
-            ExtractSection(NcaSectionType.Code);
-        }
-
-        private void ExtractLogo_Clicked(object sender, EventArgs args)
-        {
-            ExtractSection(NcaSectionType.Logo);
-        }
-
-        private void OpenPtcDir_Clicked(object sender, EventArgs args)
-        {
-            string ptcDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu");
-
-            string mainPath = System.IO.Path.Combine(ptcDir, "0");
-            string backupPath = System.IO.Path.Combine(ptcDir, "1");
-
-            if (!Directory.Exists(ptcDir))
-            {
-                Directory.CreateDirectory(ptcDir);
-                Directory.CreateDirectory(mainPath);
-                Directory.CreateDirectory(backupPath);
-            }
-
-            OpenHelper.OpenFolder(ptcDir);
-        }
-
-        private void OpenShaderCacheDir_Clicked(object sender, EventArgs args)
-        {
-            string shaderCacheDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader");
-
-            if (!Directory.Exists(shaderCacheDir))
-            {
-                Directory.CreateDirectory(shaderCacheDir);
-            }
-
-            OpenHelper.OpenFolder(shaderCacheDir);
-        }
-
-        private void PurgePtcCache_Clicked(object sender, EventArgs args)
-        {
-            DirectoryInfo mainDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "0"));
-            DirectoryInfo backupDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "1"));
-
-            MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to queue a PPTC rebuild on the next boot of:\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
-
-            List<FileInfo> cacheFiles = new();
-
-            if (mainDir.Exists)
-            {
-                cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache"));
-            }
-
-            if (backupDir.Exists)
-            {
-                cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
-            }
-
-            if (cacheFiles.Count > 0 && warningDialog.Run() == (int)ResponseType.Yes)
-            {
-                foreach (FileInfo file in cacheFiles)
-                {
-                    try
-                    {
-                        file.Delete();
-                    }
-                    catch (Exception e)
-                    {
-                        GtkDialog.CreateErrorDialog($"Error purging PPTC cache {file.Name}: {e}");
-                    }
-                }
-            }
-
-            warningDialog.Dispose();
-        }
-
-        private void PurgeShaderCache_Clicked(object sender, EventArgs args)
-        {
-            DirectoryInfo shaderCacheDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader"));
-
-            using MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to delete the shader cache for :\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
-
-            List<DirectoryInfo> oldCacheDirectories = new();
-            List<FileInfo> newCacheFiles = new();
-
-            if (shaderCacheDir.Exists)
-            {
-                oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*"));
-                newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc"));
-                newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data"));
-            }
-
-            if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0) && warningDialog.Run() == (int)ResponseType.Yes)
-            {
-                foreach (DirectoryInfo directory in oldCacheDirectories)
-                {
-                    try
-                    {
-                        directory.Delete(true);
-                    }
-                    catch (Exception e)
-                    {
-                        GtkDialog.CreateErrorDialog($"Error purging shader cache at {directory.Name}: {e}");
-                    }
-                }
-
-                foreach (FileInfo file in newCacheFiles)
-                {
-                    try
-                    {
-                        file.Delete();
-                    }
-                    catch (Exception e)
-                    {
-                        GtkDialog.CreateErrorDialog($"Error purging shader cache at {file.Name}: {e}");
-                    }
-                }
-            }
-        }
-
-        private void CreateShortcut_Clicked(object sender, EventArgs args)
-        {
-            byte[] appIcon = new ApplicationLibrary(_virtualFileSystem).GetApplicationIcon(_titleFilePath, ConfigurationState.Instance.System.Language);
-            ShortcutHelper.CreateAppShortcut(_titleFilePath, _titleName, _titleIdText, appIcon);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/GtkDialog.cs b/src/Ryujinx/Ui/Widgets/GtkDialog.cs
deleted file mode 100644
index 51e777fa..00000000
--- a/src/Ryujinx/Ui/Widgets/GtkDialog.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using Gtk;
-using Ryujinx.Common.Logging;
-using Ryujinx.Ui.Common.Configuration;
-using System.Collections.Generic;
-using System.Reflection;
-
-namespace Ryujinx.Ui.Widgets
-{
-    internal class GtkDialog : MessageDialog
-    {
-        private static bool _isChoiceDialogOpen;
-
-        private GtkDialog(string title, string mainText, string secondaryText, MessageType messageType = MessageType.Other, ButtonsType buttonsType = ButtonsType.Ok)
-            : base(null, DialogFlags.Modal, messageType, buttonsType, null)
-        {
-            Title = title;
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-            Text = mainText;
-            SecondaryText = secondaryText;
-            WindowPosition = WindowPosition.Center;
-            SecondaryUseMarkup = true;
-
-            Response += GtkDialog_Response;
-
-            SetSizeRequest(200, 20);
-        }
-
-        private void GtkDialog_Response(object sender, ResponseArgs args)
-        {
-            Dispose();
-        }
-
-        internal static void CreateInfoDialog(string mainText, string secondaryText)
-        {
-            new GtkDialog("Ryujinx - Info", mainText, secondaryText, MessageType.Info).Run();
-        }
-
-        internal static void CreateUpdaterInfoDialog(string mainText, string secondaryText)
-        {
-            new GtkDialog("Ryujinx - Updater", mainText, secondaryText, MessageType.Info).Run();
-        }
-
-        internal static MessageDialog CreateWaitingDialog(string mainText, string secondaryText)
-        {
-            return new GtkDialog("Ryujinx - Waiting", mainText, secondaryText, MessageType.Info, ButtonsType.None);
-        }
-
-        internal static void CreateWarningDialog(string mainText, string secondaryText)
-        {
-            new GtkDialog("Ryujinx - Warning", mainText, secondaryText, MessageType.Warning).Run();
-        }
-
-        internal static void CreateErrorDialog(string errorMessage)
-        {
-            Logger.Error?.Print(LogClass.Application, errorMessage);
-
-            new GtkDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage, MessageType.Error).Run();
-        }
-
-        internal static MessageDialog CreateConfirmationDialog(string mainText, string secondaryText = "")
-        {
-            return new GtkDialog("Ryujinx - Confirmation", mainText, secondaryText, MessageType.Question, ButtonsType.YesNo);
-        }
-
-        internal static bool CreateChoiceDialog(string title, string mainText, string secondaryText)
-        {
-            if (_isChoiceDialogOpen)
-            {
-                return false;
-            }
-
-            _isChoiceDialogOpen = true;
-
-            ResponseType response = (ResponseType)new GtkDialog(title, mainText, secondaryText, MessageType.Question, ButtonsType.YesNo).Run();
-
-            _isChoiceDialogOpen = false;
-
-            return response == ResponseType.Yes;
-        }
-
-        internal static ResponseType CreateCustomDialog(string title, string mainText, string secondaryText, Dictionary<int, string> buttons, MessageType messageType = MessageType.Other)
-        {
-            GtkDialog gtkDialog = new(title, mainText, secondaryText, messageType, ButtonsType.None);
-
-            foreach (var button in buttons)
-            {
-                gtkDialog.AddButton(button.Value, button.Key);
-            }
-
-            return (ResponseType)gtkDialog.Run();
-        }
-
-        internal static string CreateInputDialog(Window parent, string title, string mainText, uint inputMax)
-        {
-            GtkInputDialog gtkDialog = new(parent, title, mainText, inputMax);
-            ResponseType response = (ResponseType)gtkDialog.Run();
-            string responseText = gtkDialog.InputEntry.Text.TrimEnd();
-
-            gtkDialog.Dispose();
-
-            if (response == ResponseType.Ok)
-            {
-                return responseText;
-            }
-
-            return "";
-        }
-
-        internal static bool CreateExitDialog()
-        {
-            return CreateChoiceDialog("Ryujinx - Exit", "Are you sure you want to close Ryujinx?", "All unsaved data will be lost!");
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/GtkInputDialog.cs b/src/Ryujinx/Ui/Widgets/GtkInputDialog.cs
deleted file mode 100644
index 62298092..00000000
--- a/src/Ryujinx/Ui/Widgets/GtkInputDialog.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Gtk;
-
-namespace Ryujinx.Ui.Widgets
-{
-    public class GtkInputDialog : MessageDialog
-    {
-        public Entry InputEntry { get; }
-
-        public GtkInputDialog(Window parent, string title, string mainText, uint inputMax) : base(parent, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.OkCancel, null)
-        {
-            SetDefaultSize(300, 0);
-
-            Title = title;
-
-            Label mainTextLabel = new()
-            {
-                Text = mainText,
-            };
-
-            InputEntry = new Entry
-            {
-                MaxLength = (int)inputMax,
-            };
-
-            Label inputMaxTextLabel = new()
-            {
-                Text = $"(Max length: {inputMax})",
-            };
-
-            ((Box)MessageArea).PackStart(mainTextLabel, true, true, 0);
-            ((Box)MessageArea).PackStart(InputEntry, true, true, 5);
-            ((Box)MessageArea).PackStart(inputMaxTextLabel, true, true, 0);
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/ProfileDialog.cs b/src/Ryujinx/Ui/Widgets/ProfileDialog.cs
deleted file mode 100644
index 0731b37a..00000000
--- a/src/Ryujinx/Ui/Widgets/ProfileDialog.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using Gtk;
-using Ryujinx.Ui.Common.Configuration;
-using System;
-using System.Reflection;
-using GUI = Gtk.Builder.ObjectAttribute;
-
-namespace Ryujinx.Ui.Widgets
-{
-    public class ProfileDialog : Dialog
-    {
-        public string FileName { get; private set; }
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] Entry _profileEntry;
-        [GUI] Label _errorMessage;
-#pragma warning restore CS0649, IDE0044
-
-        public ProfileDialog() : this(new Builder("Ryujinx.Ui.Widgets.ProfileDialog.glade")) { }
-
-        private ProfileDialog(Builder builder) : base(builder.GetRawOwnedObject("_profileDialog"))
-        {
-            builder.Autoconnect(this);
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-        }
-
-        private void OkToggle_Activated(object sender, EventArgs args)
-        {
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-
-            bool validFileName = true;
-
-            foreach (char invalidChar in System.IO.Path.GetInvalidFileNameChars())
-            {
-                if (_profileEntry.Text.Contains(invalidChar))
-                {
-                    validFileName = false;
-                }
-            }
-
-            if (validFileName && !string.IsNullOrEmpty(_profileEntry.Text))
-            {
-                FileName = $"{_profileEntry.Text}.json";
-
-                Respond(ResponseType.Ok);
-            }
-            else
-            {
-                _errorMessage.Text = "The file name contains invalid characters. Please try again.";
-            }
-        }
-
-        private void CancelToggle_Activated(object sender, EventArgs args)
-        {
-            Respond(ResponseType.Cancel);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/ProfileDialog.glade b/src/Ryujinx/Ui/Widgets/ProfileDialog.glade
deleted file mode 100644
index adaf6608..00000000
--- a/src/Ryujinx/Ui/Widgets/ProfileDialog.glade
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkDialog" id="_profileDialog">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - Profile Dialog</property>
-    <property name="modal">True</property>
-    <property name="window_position">center</property>
-    <property name="default_width">400</property>
-    <property name="type_hint">dialog</property>
-    <child>
-      <placeholder/>
-    </child>
-    <child internal-child="vbox">
-      <object class="GtkBox">
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox">
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkToggleButton" id="OkToggle">
-                <property name="label" translatable="yes">OK</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <signal name="toggled" handler="OkToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToggleButton" id="CancelToggle">
-                <property name="label" translatable="yes">Cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <signal name="toggled" handler="CancelToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="padding">5</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkLabel">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="margin_top">20</property>
-                <property name="margin_bottom">10</property>
-                <property name="label" translatable="yes">Enter a name for the new profile:</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkEntry" id="_profileEntry">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="margin_left">20</property>
-                <property name="margin_right">20</property>
-                <property name="margin_top">20</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="_errorMessage">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="halign">start</property>
-                <property name="margin_left">20</property>
-                <property name="margin_right">10</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <attributes>
-                  <attribute name="foreground" value="#ffff00000000"/>
-                </attributes>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Widgets/RawInputToTextEntry.cs b/src/Ryujinx/Ui/Widgets/RawInputToTextEntry.cs
deleted file mode 100644
index e82a3d49..00000000
--- a/src/Ryujinx/Ui/Widgets/RawInputToTextEntry.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Gtk;
-
-namespace Ryujinx.Ui.Widgets
-{
-    public class RawInputToTextEntry : Entry
-    {
-        public void SendKeyPressEvent(object o, KeyPressEventArgs args)
-        {
-            base.OnKeyPressEvent(args.Event);
-        }
-
-        public void SendKeyReleaseEvent(object o, KeyReleaseEventArgs args)
-        {
-            base.OnKeyReleaseEvent(args.Event);
-        }
-
-        public void SendButtonPressEvent(object o, ButtonPressEventArgs args)
-        {
-            base.OnButtonPressEvent(args.Event);
-        }
-
-        public void SendButtonReleaseEvent(object o, ButtonReleaseEventArgs args)
-        {
-            base.OnButtonReleaseEvent(args.Event);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Widgets/UserErrorDialog.cs b/src/Ryujinx/Ui/Widgets/UserErrorDialog.cs
deleted file mode 100644
index 63a280e6..00000000
--- a/src/Ryujinx/Ui/Widgets/UserErrorDialog.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-using Gtk;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Helper;
-
-namespace Ryujinx.Ui.Widgets
-{
-    internal class UserErrorDialog : MessageDialog
-    {
-        private const string SetupGuideUrl = "https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide";
-        private const int OkResponseId = 0;
-        private const int SetupGuideResponseId = 1;
-
-        private readonly UserError _userError;
-
-        private UserErrorDialog(UserError error) : base(null, DialogFlags.Modal, MessageType.Error, ButtonsType.None, null)
-        {
-            _userError = error;
-
-            WindowPosition = WindowPosition.Center;
-            SecondaryUseMarkup = true;
-
-            Response += UserErrorDialog_Response;
-
-            SetSizeRequest(120, 50);
-
-            AddButton("OK", OkResponseId);
-
-            bool isInSetupGuide = IsCoveredBySetupGuide(error);
-
-            if (isInSetupGuide)
-            {
-                AddButton("Open the Setup Guide", SetupGuideResponseId);
-            }
-
-            string errorCode = GetErrorCode(error);
-
-            SecondaryUseMarkup = true;
-
-            Title = $"Ryujinx error ({errorCode})";
-            Text = $"{errorCode}: {GetErrorTitle(error)}";
-            SecondaryText = GetErrorDescription(error);
-
-            if (isInSetupGuide)
-            {
-                SecondaryText += "\n<b>For more information on how to fix this error, follow our Setup Guide.</b>";
-            }
-        }
-
-        private static string GetErrorCode(UserError error)
-        {
-            return $"RYU-{(uint)error:X4}";
-        }
-
-        private static string GetErrorTitle(UserError error)
-        {
-            return error switch
-            {
-                UserError.NoKeys => "Keys not found",
-                UserError.NoFirmware => "Firmware not found",
-                UserError.FirmwareParsingFailed => "Firmware parsing error",
-                UserError.ApplicationNotFound => "Application not found",
-                UserError.Unknown => "Unknown error",
-                _ => "Undefined error",
-            };
-        }
-
-        private static string GetErrorDescription(UserError error)
-        {
-            return error switch
-            {
-                UserError.NoKeys => "Ryujinx was unable to find your 'prod.keys' file",
-                UserError.NoFirmware => "Ryujinx was unable to find any firmwares installed",
-                UserError.FirmwareParsingFailed => "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
-                UserError.ApplicationNotFound => "Ryujinx couldn't find a valid application at the given path.",
-                UserError.Unknown => "An unknown error occured!",
-                _ => "An undefined error occured! This shouldn't happen, please contact a dev!",
-            };
-        }
-
-        private static bool IsCoveredBySetupGuide(UserError error)
-        {
-            return error switch
-            {
-                UserError.NoKeys or
-                UserError.NoFirmware or
-                UserError.FirmwareParsingFailed => true,
-                _ => false,
-            };
-        }
-
-        private static string GetSetupGuideUrl(UserError error)
-        {
-            if (!IsCoveredBySetupGuide(error))
-            {
-                return null;
-            }
-
-            return error switch
-            {
-                UserError.NoKeys => SetupGuideUrl + "#initial-setup---placement-of-prodkeys",
-                UserError.NoFirmware => SetupGuideUrl + "#initial-setup-continued---installation-of-firmware",
-                _ => SetupGuideUrl,
-            };
-        }
-
-        private void UserErrorDialog_Response(object sender, ResponseArgs args)
-        {
-            int responseId = (int)args.ResponseId;
-
-            if (responseId == SetupGuideResponseId)
-            {
-                OpenHelper.OpenUrl(GetSetupGuideUrl(_userError));
-            }
-
-            Dispose();
-        }
-
-        public static void CreateUserErrorDialog(UserError error)
-        {
-            new UserErrorDialog(error).Run();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/AboutWindow.Designer.cs b/src/Ryujinx/Ui/Windows/AboutWindow.Designer.cs
deleted file mode 100644
index 34502633..00000000
--- a/src/Ryujinx/Ui/Windows/AboutWindow.Designer.cs
+++ /dev/null
@@ -1,511 +0,0 @@
-using Gtk;
-using Pango;
-using Ryujinx.Ui.Common.Configuration;
-using System.Reflection;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class AboutWindow : Window
-    {
-        private Box _mainBox;
-        private Box _leftBox;
-        private Box _logoBox;
-        private Image _ryujinxLogo;
-        private Box _logoTextBox;
-        private Label _ryujinxLabel;
-        private Label _ryujinxPhoneticLabel;
-        private EventBox _ryujinxLink;
-        private Label _ryujinxLinkLabel;
-        private Label _versionLabel;
-        private Label _disclaimerLabel;
-        private EventBox _amiiboApiLink;
-        private Label _amiiboApiLinkLabel;
-        private Box _socialBox;
-        private EventBox _patreonEventBox;
-        private Box _patreonBox;
-        private Image _patreonLogo;
-        private Label _patreonLabel;
-        private EventBox _githubEventBox;
-        private Box _githubBox;
-        private Image _githubLogo;
-        private Label _githubLabel;
-        private Box _discordBox;
-        private EventBox _discordEventBox;
-        private Image _discordLogo;
-        private Label _discordLabel;
-        private EventBox _twitterEventBox;
-        private Box _twitterBox;
-        private Image _twitterLogo;
-        private Label _twitterLabel;
-        private Separator _separator;
-        private Box _rightBox;
-        private Label _aboutLabel;
-        private Label _aboutDescriptionLabel;
-        private Label _createdByLabel;
-        private TextView _createdByText;
-        private EventBox _contributorsEventBox;
-        private Label _contributorsLinkLabel;
-        private Label _patreonNamesLabel;
-        private ScrolledWindow _patreonNamesScrolled;
-        private TextView _patreonNamesText;
-        private EventBox _changelogEventBox;
-        private Label _changelogLinkLabel;
-
-        private void InitializeComponent()
-        {
-
-            //
-            // AboutWindow
-            //
-            CanFocus = false;
-            Resizable = false;
-            Modal = true;
-            WindowPosition = WindowPosition.Center;
-            DefaultWidth = 800;
-            DefaultHeight = 450;
-            TypeHint = Gdk.WindowTypeHint.Dialog;
-
-            //
-            // _mainBox
-            //
-            _mainBox = new Box(Orientation.Horizontal, 0);
-
-            //
-            // _leftBox
-            //
-            _leftBox = new Box(Orientation.Vertical, 0)
-            {
-                Margin = 15,
-                MarginStart = 30,
-                MarginEnd = 0,
-            };
-
-            //
-            // _logoBox
-            //
-            _logoBox = new Box(Orientation.Horizontal, 0);
-
-            //
-            // _ryujinxLogo
-            //
-            _ryujinxLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png", 100, 100))
-            {
-                Margin = 10,
-                MarginStart = 15,
-            };
-
-            //
-            // _logoTextBox
-            //
-            _logoTextBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _ryujinxLabel
-            //
-            _ryujinxLabel = new Label("Ryujinx")
-            {
-                MarginTop = 15,
-                Justify = Justification.Center,
-                Attributes = new AttrList(),
-            };
-            _ryujinxLabel.Attributes.Insert(new Pango.AttrScale(2.7f));
-
-            //
-            // _ryujinxPhoneticLabel
-            //
-            _ryujinxPhoneticLabel = new Label("(REE-YOU-JINX)")
-            {
-                Justify = Justification.Center,
-            };
-
-            //
-            // _ryujinxLink
-            //
-            _ryujinxLink = new EventBox()
-            {
-                Margin = 5
-            };
-            _ryujinxLink.ButtonPressEvent += RyujinxButton_Pressed;
-
-            //
-            // _ryujinxLinkLabel
-            //
-            _ryujinxLinkLabel = new Label("www.ryujinx.org")
-            {
-                TooltipText = "Click to open the Ryujinx website in your default browser.",
-                Justify = Justification.Center,
-                Attributes = new AttrList(),
-            };
-            _ryujinxLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _versionLabel
-            //
-            _versionLabel = new Label(Program.Version)
-            {
-                Expand = true,
-                Justify = Justification.Center,
-                Margin = 5,
-            };
-
-            //
-            // _changelogEventBox
-            //
-            _changelogEventBox = new EventBox();
-            _changelogEventBox.ButtonPressEvent += ChangelogButton_Pressed;
-
-            //
-            // _changelogLinkLabel
-            //
-            _changelogLinkLabel = new Label("View Changelog on GitHub")
-            {
-                TooltipText = "Click to open the changelog for this version in your default browser.",
-                Justify = Justification.Center,
-                Attributes = new AttrList(),
-            };
-            _changelogLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _disclaimerLabel
-            //
-            _disclaimerLabel = new Label("Ryujinx is not affiliated with Nintendo™,\nor any of its partners, in any way.")
-            {
-                Expand = true,
-                Justify = Justification.Center,
-                Margin = 5,
-                Attributes = new AttrList(),
-            };
-            _disclaimerLabel.Attributes.Insert(new Pango.AttrScale(0.8f));
-
-            //
-            // _amiiboApiLink
-            //
-            _amiiboApiLink = new EventBox()
-            {
-                Margin = 5,
-            };
-            _amiiboApiLink.ButtonPressEvent += AmiiboApiButton_Pressed;
-
-            //
-            // _amiiboApiLinkLabel
-            //
-            _amiiboApiLinkLabel = new Label("AmiiboAPI (www.amiiboapi.com) is used\nin our Amiibo emulation.")
-            {
-                TooltipText = "Click to open the AmiiboAPI website in your default browser.",
-                Justify = Justification.Center,
-                Attributes = new AttrList(),
-            };
-            _amiiboApiLinkLabel.Attributes.Insert(new Pango.AttrScale(0.9f));
-
-            //
-            // _socialBox
-            //
-            _socialBox = new Box(Orientation.Horizontal, 0)
-            {
-                Margin = 25,
-                MarginBottom = 10,
-            };
-
-            //
-            // _patreonEventBox
-            //
-            _patreonEventBox = new EventBox()
-            {
-                TooltipText = "Click to open the Ryujinx Patreon page in your default browser.",
-            };
-            _patreonEventBox.ButtonPressEvent += PatreonButton_Pressed;
-
-            //
-            // _patreonBox
-            //
-            _patreonBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _patreonLogo
-            //
-            _patreonLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Patreon_Light.png", 30, 30))
-            {
-                Margin = 10,
-            };
-
-            //
-            // _patreonLabel
-            //
-            _patreonLabel = new Label("Patreon")
-            {
-                Justify = Justification.Center,
-            };
-
-            //
-            // _githubEventBox
-            //
-            _githubEventBox = new EventBox()
-            {
-                TooltipText = "Click to open the Ryujinx GitHub page in your default browser.",
-            };
-            _githubEventBox.ButtonPressEvent += GitHubButton_Pressed;
-
-            //
-            // _githubBox
-            //
-            _githubBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _githubLogo
-            //
-            _githubLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_GitHub_Light.png", 30, 30))
-            {
-                Margin = 10,
-            };
-
-            //
-            // _githubLabel
-            //
-            _githubLabel = new Label("GitHub")
-            {
-                Justify = Justification.Center,
-            };
-
-            //
-            // _discordBox
-            //
-            _discordBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _discordEventBox
-            //
-            _discordEventBox = new EventBox()
-            {
-                TooltipText = "Click to open an invite to the Ryujinx Discord server in your default browser.",
-            };
-            _discordEventBox.ButtonPressEvent += DiscordButton_Pressed;
-
-            //
-            // _discordLogo
-            //
-            _discordLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Discord_Light.png", 30, 30))
-            {
-                Margin = 10,
-            };
-
-            //
-            // _discordLabel
-            //
-            _discordLabel = new Label("Discord")
-            {
-                Justify = Justification.Center,
-            };
-
-            //
-            // _twitterEventBox
-            //
-            _twitterEventBox = new EventBox()
-            {
-                TooltipText = "Click to open the Ryujinx Twitter page in your default browser.",
-            };
-            _twitterEventBox.ButtonPressEvent += TwitterButton_Pressed;
-
-            //
-            // _twitterBox
-            //
-            _twitterBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _twitterLogo
-            //
-            _twitterLogo = new Image(new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Twitter_Light.png", 30, 30))
-            {
-                Margin = 10,
-            };
-
-            //
-            // _twitterLabel
-            //
-            _twitterLabel = new Label("Twitter")
-            {
-                Justify = Justification.Center,
-            };
-
-            //
-            // _separator
-            //
-            _separator = new Separator(Orientation.Vertical)
-            {
-                Margin = 15,
-            };
-
-            //
-            // _rightBox
-            //
-            _rightBox = new Box(Orientation.Vertical, 0)
-            {
-                Margin = 15,
-                MarginTop = 40,
-            };
-
-            //
-            // _aboutLabel
-            //
-            _aboutLabel = new Label("About :")
-            {
-                Halign = Align.Start,
-                Attributes = new AttrList(),
-            };
-            _aboutLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
-            _aboutLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _aboutDescriptionLabel
-            //
-            _aboutDescriptionLabel = new Label("Ryujinx is an emulator for the Nintendo Switch™.\n" +
-                                               "Please support us on Patreon.\n" +
-                                               "Get all the latest news on our Twitter or Discord.\n" +
-                                               "Developers interested in contributing can find out more on our GitHub or Discord.")
-            {
-                Margin = 15,
-                Halign = Align.Start,
-            };
-
-            //
-            // _createdByLabel
-            //
-            _createdByLabel = new Label("Maintained by :")
-            {
-                Halign = Align.Start,
-                Attributes = new AttrList(),
-            };
-            _createdByLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
-            _createdByLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _createdByText
-            //
-            _createdByText = new TextView()
-            {
-                WrapMode = Gtk.WrapMode.Word,
-                Editable = false,
-                CursorVisible = false,
-                Margin = 15,
-                MarginEnd = 30,
-            };
-            _createdByText.Buffer.Text = "gdkchan, Ac_K, Thog, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, Xpl0itR, GoffyDude, »jD« and more...";
-
-            //
-            // _contributorsEventBox
-            //
-            _contributorsEventBox = new EventBox();
-            _contributorsEventBox.ButtonPressEvent += ContributorsButton_Pressed;
-
-            //
-            // _contributorsLinkLabel
-            //
-            _contributorsLinkLabel = new Label("See All Contributors...")
-            {
-                TooltipText = "Click to open the Contributors page in your default browser.",
-                MarginEnd = 30,
-                Halign = Align.End,
-                Attributes = new AttrList(),
-            };
-            _contributorsLinkLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _patreonNamesLabel
-            //
-            _patreonNamesLabel = new Label("Supported on Patreon by :")
-            {
-                Halign = Align.Start,
-                Attributes = new AttrList(),
-            };
-            _patreonNamesLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
-            _patreonNamesLabel.Attributes.Insert(new Pango.AttrUnderline(Underline.Single));
-
-            //
-            // _patreonNamesScrolled
-            //
-            _patreonNamesScrolled = new ScrolledWindow()
-            {
-                Margin = 15,
-                MarginEnd = 30,
-                Expand = true,
-                ShadowType = ShadowType.In,
-            };
-            _patreonNamesScrolled.SetPolicy(PolicyType.Never, PolicyType.Automatic);
-
-            //
-            // _patreonNamesText
-            //
-            _patreonNamesText = new TextView()
-            {
-                WrapMode = Gtk.WrapMode.Word,
-            };
-            _patreonNamesText.Buffer.Text = "Loading...";
-            _patreonNamesText.SetProperty("editable", new GLib.Value(false));
-
-            ShowComponent();
-        }
-
-        private void ShowComponent()
-        {
-            _logoBox.Add(_ryujinxLogo);
-
-            _ryujinxLink.Add(_ryujinxLinkLabel);
-
-            _logoTextBox.Add(_ryujinxLabel);
-            _logoTextBox.Add(_ryujinxPhoneticLabel);
-            _logoTextBox.Add(_ryujinxLink);
-
-            _logoBox.Add(_logoTextBox);
-
-            _amiiboApiLink.Add(_amiiboApiLinkLabel);
-
-            _patreonBox.Add(_patreonLogo);
-            _patreonBox.Add(_patreonLabel);
-            _patreonEventBox.Add(_patreonBox);
-
-            _githubBox.Add(_githubLogo);
-            _githubBox.Add(_githubLabel);
-            _githubEventBox.Add(_githubBox);
-
-            _discordBox.Add(_discordLogo);
-            _discordBox.Add(_discordLabel);
-            _discordEventBox.Add(_discordBox);
-
-            _twitterBox.Add(_twitterLogo);
-            _twitterBox.Add(_twitterLabel);
-            _twitterEventBox.Add(_twitterBox);
-
-            _socialBox.Add(_patreonEventBox);
-            _socialBox.Add(_githubEventBox);
-            _socialBox.Add(_discordEventBox);
-            _socialBox.Add(_twitterEventBox);
-
-            _changelogEventBox.Add(_changelogLinkLabel);
-
-            _leftBox.Add(_logoBox);
-            _leftBox.Add(_versionLabel);
-            _leftBox.Add(_changelogEventBox);
-            _leftBox.Add(_disclaimerLabel);
-            _leftBox.Add(_amiiboApiLink);
-            _leftBox.Add(_socialBox);
-
-            _contributorsEventBox.Add(_contributorsLinkLabel);
-            _patreonNamesScrolled.Add(_patreonNamesText);
-
-            _rightBox.Add(_aboutLabel);
-            _rightBox.Add(_aboutDescriptionLabel);
-            _rightBox.Add(_createdByLabel);
-            _rightBox.Add(_createdByText);
-            _rightBox.Add(_contributorsEventBox);
-            _rightBox.Add(_patreonNamesLabel);
-            _rightBox.Add(_patreonNamesScrolled);
-
-            _mainBox.Add(_leftBox);
-            _mainBox.Add(_separator);
-            _mainBox.Add(_rightBox);
-
-            Add(_mainBox);
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/AboutWindow.cs b/src/Ryujinx/Ui/Windows/AboutWindow.cs
deleted file mode 100644
index ba12bb68..00000000
--- a/src/Ryujinx/Ui/Windows/AboutWindow.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Gtk;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Helper;
-using System.Net.Http;
-using System.Net.NetworkInformation;
-using System.Reflection;
-using System.Threading.Tasks;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class AboutWindow : Window
-    {
-        public AboutWindow() : base($"Ryujinx {Program.Version} - About")
-        {
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(OpenHelper)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-            InitializeComponent();
-
-            _ = DownloadPatronsJson();
-        }
-
-        private async Task DownloadPatronsJson()
-        {
-            if (!NetworkInterface.GetIsNetworkAvailable())
-            {
-                _patreonNamesText.Buffer.Text = "Connection Error.";
-            }
-
-            HttpClient httpClient = new();
-
-            try
-            {
-                string patreonJsonString = await httpClient.GetStringAsync("https://patreon.ryujinx.org/");
-
-                _patreonNamesText.Buffer.Text = string.Join(", ", JsonHelper.Deserialize(patreonJsonString, CommonJsonContext.Default.StringArray));
-            }
-            catch
-            {
-                _patreonNamesText.Buffer.Text = "API Error.";
-            }
-        }
-
-        //
-        // Events
-        //
-        private void RyujinxButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://ryujinx.org");
-        }
-
-        private void AmiiboApiButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://amiiboapi.com");
-        }
-
-        private void PatreonButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://www.patreon.com/ryujinx");
-        }
-
-        private void GitHubButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx");
-        }
-
-        private void DiscordButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://discordapp.com/invite/N2FmfVc");
-        }
-
-        private void TwitterButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://twitter.com/RyujinxEmu");
-        }
-
-        private void ContributorsButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx/graphs/contributors?type=a");
-        }
-
-        private void ChangelogButton_Pressed(object sender, ButtonPressEventArgs args)
-        {
-            OpenHelper.OpenUrl("https://github.com/Ryujinx/Ryujinx/wiki/Changelog#ryujinx-changelog");
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/AmiiboWindow.Designer.cs b/src/Ryujinx/Ui/Windows/AmiiboWindow.Designer.cs
deleted file mode 100644
index cb27c34c..00000000
--- a/src/Ryujinx/Ui/Windows/AmiiboWindow.Designer.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-using Gtk;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class AmiiboWindow : Window
-    {
-        private Box _mainBox;
-        private ButtonBox _buttonBox;
-        private Button _scanButton;
-        private Button _cancelButton;
-        private CheckButton _randomUuidCheckBox;
-        private Box _amiiboBox;
-        private Box _amiiboHeadBox;
-        private Box _amiiboSeriesBox;
-        private Label _amiiboSeriesLabel;
-        private ComboBoxText _amiiboSeriesComboBox;
-        private Box _amiiboCharsBox;
-        private Label _amiiboCharsLabel;
-        private ComboBoxText _amiiboCharsComboBox;
-        private CheckButton _showAllCheckBox;
-        private Image _amiiboImage;
-        private Label _gameUsageLabel;
-
-        private void InitializeComponent()
-        {
-            //
-            // AmiiboWindow
-            //
-            CanFocus = false;
-            Resizable = false;
-            Modal = true;
-            WindowPosition = WindowPosition.Center;
-            DefaultWidth = 600;
-            DefaultHeight = 470;
-            TypeHint = Gdk.WindowTypeHint.Dialog;
-
-            //
-            // _mainBox
-            //
-            _mainBox = new Box(Orientation.Vertical, 2);
-
-            //
-            // _buttonBox
-            //
-            _buttonBox = new ButtonBox(Orientation.Horizontal)
-            {
-                Margin = 20,
-                LayoutStyle = ButtonBoxStyle.End,
-            };
-
-            //
-            // _scanButton
-            //
-            _scanButton = new Button()
-            {
-                Label = "Scan It!",
-                CanFocus = true,
-                ReceivesDefault = true,
-                MarginStart = 10,
-            };
-            _scanButton.Clicked += ScanButton_Pressed;
-
-            //
-            // _randomUuidCheckBox
-            //
-            _randomUuidCheckBox = new CheckButton()
-            {
-                Label = "Hack: Use Random Tag Uuid",
-                TooltipText = "This allows multiple scans of a single Amiibo.\n(used in The Legend of Zelda: Breath of the Wild)",
-            };
-
-            //
-            // _cancelButton
-            //
-            _cancelButton = new Button()
-            {
-                Label = "Cancel",
-                CanFocus = true,
-                ReceivesDefault = true,
-                MarginStart = 10,
-            };
-            _cancelButton.Clicked += CancelButton_Pressed;
-
-            //
-            // _amiiboBox
-            //
-            _amiiboBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _amiiboHeadBox
-            //
-            _amiiboHeadBox = new Box(Orientation.Horizontal, 0)
-            {
-                Margin = 20,
-                Hexpand = true,
-            };
-
-            //
-            // _amiiboSeriesBox
-            //
-            _amiiboSeriesBox = new Box(Orientation.Horizontal, 0)
-            {
-                Hexpand = true,
-            };
-
-            //
-            // _amiiboSeriesLabel
-            //
-            _amiiboSeriesLabel = new Label("Amiibo Series:");
-
-            //
-            // _amiiboSeriesComboBox
-            //
-            _amiiboSeriesComboBox = new ComboBoxText();
-
-            //
-            // _amiiboCharsBox
-            //
-            _amiiboCharsBox = new Box(Orientation.Horizontal, 0)
-            {
-                Hexpand = true,
-            };
-
-            //
-            // _amiiboCharsLabel
-            //
-            _amiiboCharsLabel = new Label("Character:");
-
-            //
-            // _amiiboCharsComboBox
-            //
-            _amiiboCharsComboBox = new ComboBoxText();
-
-            //
-            // _showAllCheckBox
-            //
-            _showAllCheckBox = new CheckButton()
-            {
-                Label = "Show All Amiibo",
-            };
-
-            //
-            // _amiiboImage
-            //
-            _amiiboImage = new Image()
-            {
-                HeightRequest = 350,
-                WidthRequest = 350,
-            };
-
-            //
-            // _gameUsageLabel
-            //
-            _gameUsageLabel = new Label("")
-            {
-                MarginTop = 20,
-            };
-
-            ShowComponent();
-        }
-
-        private void ShowComponent()
-        {
-            _buttonBox.Add(_showAllCheckBox);
-            _buttonBox.Add(_randomUuidCheckBox);
-            _buttonBox.Add(_scanButton);
-            _buttonBox.Add(_cancelButton);
-
-            _amiiboSeriesBox.Add(_amiiboSeriesLabel);
-            _amiiboSeriesBox.Add(_amiiboSeriesComboBox);
-
-            _amiiboCharsBox.Add(_amiiboCharsLabel);
-            _amiiboCharsBox.Add(_amiiboCharsComboBox);
-
-            _amiiboHeadBox.Add(_amiiboSeriesBox);
-            _amiiboHeadBox.Add(_amiiboCharsBox);
-
-            _amiiboBox.PackStart(_amiiboHeadBox, true, true, 0);
-            _amiiboBox.PackEnd(_gameUsageLabel, false, false, 0);
-            _amiiboBox.PackEnd(_amiiboImage, false, false, 0);
-
-            _mainBox.Add(_amiiboBox);
-            _mainBox.PackEnd(_buttonBox, false, false, 0);
-
-            Add(_mainBox);
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/AmiiboWindow.cs b/src/Ryujinx/Ui/Windows/AmiiboWindow.cs
deleted file mode 100644
index a2a5bce6..00000000
--- a/src/Ryujinx/Ui/Windows/AmiiboWindow.cs
+++ /dev/null
@@ -1,438 +0,0 @@
-using Gdk;
-using Gtk;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Models.Amiibo;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Reflection;
-using System.Text;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Window = Gtk.Window;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class AmiiboWindow : Window
-    {
-        private const string DefaultJson = "{ \"amiibo\": [] }";
-
-        public string AmiiboId { get; private set; }
-
-        public int DeviceId { get; set; }
-        public string TitleId { get; set; }
-        public string LastScannedAmiiboId { get; set; }
-        public bool LastScannedAmiiboShowAll { get; set; }
-
-        public ResponseType Response { get; private set; }
-
-        public bool UseRandomUuid
-        {
-            get
-            {
-                return _randomUuidCheckBox.Active;
-            }
-        }
-
-        private readonly HttpClient _httpClient;
-        private readonly string _amiiboJsonPath;
-
-        private readonly byte[] _amiiboLogoBytes;
-
-        private List<AmiiboApi> _amiiboList;
-
-        private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-        public AmiiboWindow() : base($"Ryujinx {Program.Version} - Amiibo")
-        {
-            Icon = new Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            InitializeComponent();
-
-            _httpClient = new HttpClient
-            {
-                Timeout = TimeSpan.FromSeconds(30),
-            };
-
-            Directory.CreateDirectory(System.IO.Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
-
-            _amiiboJsonPath = System.IO.Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", "Amiibo.json");
-            _amiiboList = new List<AmiiboApi>();
-
-            _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.Ui.Common/Resources/Logo_Amiibo.png");
-            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
-
-            _scanButton.Sensitive = false;
-            _randomUuidCheckBox.Sensitive = false;
-
-            _ = LoadContentAsync();
-        }
-
-        private static bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
-        {
-            if (string.IsNullOrEmpty(json))
-            {
-                amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
-
-                return false;
-            }
-
-            try
-            {
-                amiiboJson = JsonHelper.Deserialize(json, _serializerContext.AmiiboJson);
-
-                return true;
-            }
-            catch (JsonException exception)
-            {
-                Logger.Error?.Print(LogClass.Application, $"Unable to deserialize amiibo data: {exception}");
-                amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
-
-                return false;
-            }
-        }
-
-        private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
-        {
-            bool localIsValid = false;
-            bool remoteIsValid = false;
-            AmiiboJson amiiboJson = new();
-
-            try
-            {
-                try
-                {
-                    if (File.Exists(_amiiboJsonPath))
-                    {
-                        localIsValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson);
-                    }
-                }
-                catch (Exception exception)
-                {
-                    Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
-                }
-
-                if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
-                {
-                    remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
-                }
-            }
-            catch (Exception exception)
-            {
-                if (!(localIsValid || remoteIsValid))
-                {
-                    Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
-
-                    // Neither local or remote files are valid JSON, close window.
-                    ShowInfoDialog();
-                    Close();
-                }
-                else if (!remoteIsValid)
-                {
-                    Logger.Warning?.Print(LogClass.Application, $"Couldn't update amiibo data: {exception}");
-
-                    // Only the local file is valid, the local one should be used
-                    // but the user should be warned.
-                    ShowInfoDialog();
-                }
-            }
-
-            return amiiboJson;
-        }
-
-        private async Task LoadContentAsync()
-        {
-            AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
-
-            _amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
-
-            if (LastScannedAmiiboShowAll)
-            {
-                _showAllCheckBox.Click();
-            }
-
-            ParseAmiiboData();
-
-            _showAllCheckBox.Clicked += ShowAllCheckBox_Clicked;
-        }
-
-        private void ParseAmiiboData()
-        {
-            List<string> comboxItemList = new();
-
-            for (int i = 0; i < _amiiboList.Count; i++)
-            {
-                if (!comboxItemList.Contains(_amiiboList[i].AmiiboSeries))
-                {
-                    if (!_showAllCheckBox.Active)
-                    {
-                        foreach (var game in _amiiboList[i].GamesSwitch)
-                        {
-                            if (game != null)
-                            {
-                                if (game.GameId.Contains(TitleId))
-                                {
-                                    comboxItemList.Add(_amiiboList[i].AmiiboSeries);
-                                    _amiiboSeriesComboBox.Append(_amiiboList[i].AmiiboSeries, _amiiboList[i].AmiiboSeries);
-
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        comboxItemList.Add(_amiiboList[i].AmiiboSeries);
-                        _amiiboSeriesComboBox.Append(_amiiboList[i].AmiiboSeries, _amiiboList[i].AmiiboSeries);
-                    }
-                }
-            }
-
-            _amiiboSeriesComboBox.Changed += SeriesComboBox_Changed;
-            _amiiboCharsComboBox.Changed += CharacterComboBox_Changed;
-
-            if (LastScannedAmiiboId != "")
-            {
-                SelectLastScannedAmiibo();
-            }
-            else
-            {
-                _amiiboSeriesComboBox.Active = 0;
-            }
-        }
-
-        private void SelectLastScannedAmiibo()
-        {
-            bool isSet = _amiiboSeriesComboBox.SetActiveId(_amiiboList.Find(amiibo => amiibo.Head + amiibo.Tail == LastScannedAmiiboId).AmiiboSeries);
-            isSet = _amiiboCharsComboBox.SetActiveId(LastScannedAmiiboId);
-
-            if (isSet == false)
-            {
-                _amiiboSeriesComboBox.Active = 0;
-            }
-        }
-
-        private async Task<bool> NeedsUpdate(DateTime oldLastModified)
-        {
-            try
-            {
-                HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
-
-                if (response.IsSuccessStatusCode)
-                {
-                    return response.Content.Headers.LastModified != oldLastModified;
-                }
-            }
-            catch (HttpRequestException exception)
-            {
-                Logger.Error?.Print(LogClass.Application, $"Unable to check for amiibo data updates: {exception}");
-            }
-
-            return false;
-        }
-
-        private async Task<string> DownloadAmiiboJson()
-        {
-            try
-            {
-                HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
-
-                if (response.IsSuccessStatusCode)
-                {
-                    string amiiboJsonString = await response.Content.ReadAsStringAsync();
-
-                    try
-                    {
-                        using FileStream dlcJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough);
-                        dlcJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
-                    }
-                    catch (Exception exception)
-                    {
-                        Logger.Warning?.Print(LogClass.Application, $"Couldn't write amiibo data to file '{_amiiboJsonPath}: {exception}'");
-                    }
-
-                    return amiiboJsonString;
-                }
-
-                Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
-            }
-            catch (HttpRequestException exception)
-            {
-                Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}");
-            }
-
-            GtkDialog.CreateInfoDialog("Amiibo API", "An error occured while fetching information from the API.");
-
-            return null;
-        }
-
-        private async Task UpdateAmiiboPreview(string imageUrl)
-        {
-            HttpResponseMessage response = await _httpClient.GetAsync(imageUrl);
-
-            if (response.IsSuccessStatusCode)
-            {
-                byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync();
-                Pixbuf amiiboPreview = new(amiiboPreviewBytes);
-
-                float ratio = Math.Min((float)_amiiboImage.AllocatedWidth / amiiboPreview.Width,
-                                       (float)_amiiboImage.AllocatedHeight / amiiboPreview.Height);
-
-                int resizeHeight = (int)(amiiboPreview.Height * ratio);
-                int resizeWidth = (int)(amiiboPreview.Width * ratio);
-
-                _amiiboImage.Pixbuf = amiiboPreview.ScaleSimple(resizeWidth, resizeHeight, InterpType.Bilinear);
-            }
-            else
-            {
-                Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}");
-            }
-        }
-
-        private static void ShowInfoDialog()
-        {
-            GtkDialog.CreateInfoDialog("Amiibo API", "Unable to connect to Amiibo API server. The service may be down or you may need to verify your internet connection is online.");
-        }
-
-        //
-        // Events
-        //
-        private void SeriesComboBox_Changed(object sender, EventArgs args)
-        {
-            _amiiboCharsComboBox.Changed -= CharacterComboBox_Changed;
-
-            _amiiboCharsComboBox.RemoveAll();
-
-            List<AmiiboApi> amiiboSortedList = _amiiboList.Where(amiibo => amiibo.AmiiboSeries == _amiiboSeriesComboBox.ActiveId).OrderBy(amiibo => amiibo.Name).ToList();
-
-            List<string> comboxItemList = new();
-
-            for (int i = 0; i < amiiboSortedList.Count; i++)
-            {
-                if (!comboxItemList.Contains(amiiboSortedList[i].Head + amiiboSortedList[i].Tail))
-                {
-                    if (!_showAllCheckBox.Active)
-                    {
-                        foreach (var game in amiiboSortedList[i].GamesSwitch)
-                        {
-                            if (game != null)
-                            {
-                                if (game.GameId.Contains(TitleId))
-                                {
-                                    comboxItemList.Add(amiiboSortedList[i].Head + amiiboSortedList[i].Tail);
-                                    _amiiboCharsComboBox.Append(amiiboSortedList[i].Head + amiiboSortedList[i].Tail, amiiboSortedList[i].Name);
-
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        comboxItemList.Add(amiiboSortedList[i].Head + amiiboSortedList[i].Tail);
-                        _amiiboCharsComboBox.Append(amiiboSortedList[i].Head + amiiboSortedList[i].Tail, amiiboSortedList[i].Name);
-                    }
-                }
-            }
-
-            _amiiboCharsComboBox.Changed += CharacterComboBox_Changed;
-
-            _amiiboCharsComboBox.Active = 0;
-
-            _scanButton.Sensitive = true;
-            _randomUuidCheckBox.Sensitive = true;
-        }
-
-        private void CharacterComboBox_Changed(object sender, EventArgs args)
-        {
-            AmiiboId = _amiiboCharsComboBox.ActiveId;
-
-            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
-
-            string imageUrl = _amiiboList.Find(amiibo => amiibo.Head + amiibo.Tail == _amiiboCharsComboBox.ActiveId).Image;
-
-            var usageStringBuilder = new StringBuilder();
-
-            for (int i = 0; i < _amiiboList.Count; i++)
-            {
-                if (_amiiboList[i].Head + _amiiboList[i].Tail == _amiiboCharsComboBox.ActiveId)
-                {
-                    bool writable = false;
-
-                    foreach (var item in _amiiboList[i].GamesSwitch)
-                    {
-                        if (item.GameId.Contains(TitleId))
-                        {
-                            foreach (AmiiboApiUsage usageItem in item.AmiiboUsage)
-                            {
-                                usageStringBuilder.Append(Environment.NewLine);
-                                usageStringBuilder.Append($"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
-
-                                writable = usageItem.Write;
-                            }
-                        }
-                    }
-
-                    if (usageStringBuilder.Length == 0)
-                    {
-                        usageStringBuilder.Append("Unknown.");
-                    }
-
-                    _gameUsageLabel.Text = $"Usage{(writable ? " (Writable)" : "")} : {usageStringBuilder}";
-                }
-            }
-
-            _ = UpdateAmiiboPreview(imageUrl);
-        }
-
-        private void ShowAllCheckBox_Clicked(object sender, EventArgs e)
-        {
-            _amiiboImage.Pixbuf = new Pixbuf(_amiiboLogoBytes);
-
-            _amiiboSeriesComboBox.Changed -= SeriesComboBox_Changed;
-            _amiiboCharsComboBox.Changed -= CharacterComboBox_Changed;
-
-            _amiiboSeriesComboBox.RemoveAll();
-            _amiiboCharsComboBox.RemoveAll();
-
-            _scanButton.Sensitive = false;
-            _randomUuidCheckBox.Sensitive = false;
-
-            new Task(ParseAmiiboData).Start();
-        }
-
-        private void ScanButton_Pressed(object sender, EventArgs args)
-        {
-            LastScannedAmiiboShowAll = _showAllCheckBox.Active;
-
-            Response = ResponseType.Ok;
-
-            Close();
-        }
-
-        private void CancelButton_Pressed(object sender, EventArgs args)
-        {
-            AmiiboId = "";
-            LastScannedAmiiboId = "";
-            LastScannedAmiiboShowAll = false;
-
-            Response = ResponseType.Cancel;
-
-            Close();
-        }
-
-        protected override void Dispose(bool disposing)
-        {
-            _httpClient.Dispose();
-
-            base.Dispose(disposing);
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/AvatarWindow.cs b/src/Ryujinx/Ui/Windows/AvatarWindow.cs
deleted file mode 100644
index 3d3ff7c3..00000000
--- a/src/Ryujinx/Ui/Windows/AvatarWindow.cs
+++ /dev/null
@@ -1,291 +0,0 @@
-using Gtk;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Ncm;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common.Memory;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.Common.Configuration;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Buffers.Binary;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using Image = SixLabors.ImageSharp.Image;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class AvatarWindow : Window
-    {
-        public byte[] SelectedProfileImage;
-        public bool NewUser;
-
-        private static readonly Dictionary<string, byte[]> _avatarDict = new();
-
-        private readonly ListStore _listStore;
-        private readonly IconView _iconView;
-        private readonly Button _setBackgroungColorButton;
-        private Gdk.RGBA _backgroundColor;
-
-        public AvatarWindow() : base($"Ryujinx {Program.Version} - Manage Accounts - Avatar")
-        {
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            CanFocus = false;
-            Resizable = false;
-            Modal = true;
-            TypeHint = Gdk.WindowTypeHint.Dialog;
-
-            SetDefaultSize(740, 400);
-            SetPosition(WindowPosition.Center);
-
-            Box vbox = new(Orientation.Vertical, 0);
-            Add(vbox);
-
-            ScrolledWindow scrolledWindow = new()
-            {
-                ShadowType = ShadowType.EtchedIn,
-            };
-            scrolledWindow.SetPolicy(PolicyType.Automatic, PolicyType.Automatic);
-
-            Box hbox = new(Orientation.Horizontal, 0);
-
-            Button chooseButton = new()
-            {
-                Label = "Choose",
-                CanFocus = true,
-                ReceivesDefault = true,
-            };
-            chooseButton.Clicked += ChooseButton_Pressed;
-
-            _setBackgroungColorButton = new Button()
-            {
-                Label = "Set Background Color",
-                CanFocus = true,
-            };
-            _setBackgroungColorButton.Clicked += SetBackgroungColorButton_Pressed;
-
-            _backgroundColor.Red = 1;
-            _backgroundColor.Green = 1;
-            _backgroundColor.Blue = 1;
-            _backgroundColor.Alpha = 1;
-
-            Button closeButton = new()
-            {
-                Label = "Close",
-                CanFocus = true,
-            };
-            closeButton.Clicked += CloseButton_Pressed;
-
-            vbox.PackStart(scrolledWindow, true, true, 0);
-            hbox.PackStart(chooseButton, true, true, 0);
-            hbox.PackStart(_setBackgroungColorButton, true, true, 0);
-            hbox.PackStart(closeButton, true, true, 0);
-            vbox.PackStart(hbox, false, false, 0);
-
-            _listStore = new ListStore(typeof(string), typeof(Gdk.Pixbuf));
-            _listStore.SetSortColumnId(0, SortType.Ascending);
-
-            _iconView = new IconView(_listStore)
-            {
-                ItemWidth = 64,
-                ItemPadding = 10,
-                PixbufColumn = 1,
-            };
-
-            _iconView.SelectionChanged += IconView_SelectionChanged;
-
-            scrolledWindow.Add(_iconView);
-
-            _iconView.GrabFocus();
-
-            ProcessAvatars();
-
-            ShowAll();
-        }
-
-        public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
-        {
-            if (_avatarDict.Count > 0)
-            {
-                return;
-            }
-
-            string contentPath = contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem, NcaContentType.Data);
-            string avatarPath = VirtualFileSystem.SwitchPathToSystemPath(contentPath);
-
-            if (!string.IsNullOrWhiteSpace(avatarPath))
-            {
-                using IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open);
-
-                Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
-                IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
-
-                foreach (var item in romfs.EnumerateEntries())
-                {
-                    // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
-
-                    if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
-                    {
-                        using var file = new UniqueRef<IFile>();
-
-                        romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                        using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
-                        using MemoryStream streamPng = MemoryStreamManager.Shared.GetStream();
-                        file.Get.AsStream().CopyTo(stream);
-
-                        stream.Position = 0;
-
-                        Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
-
-                        avatarImage.SaveAsPng(streamPng);
-
-                        _avatarDict.Add(item.FullPath, streamPng.ToArray());
-                    }
-                }
-            }
-        }
-
-        private void ProcessAvatars()
-        {
-            _listStore.Clear();
-
-            foreach (var avatar in _avatarDict)
-            {
-                _listStore.AppendValues(avatar.Key, new Gdk.Pixbuf(ProcessImage(avatar.Value), 96, 96));
-            }
-
-            _iconView.SelectPath(new TreePath(new[] { 0 }));
-        }
-
-        private byte[] ProcessImage(byte[] data)
-        {
-            using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
-
-            Image avatarImage = Image.Load(data, new PngDecoder());
-
-            avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(
-                (byte)(_backgroundColor.Red * 255),
-                (byte)(_backgroundColor.Green * 255),
-                (byte)(_backgroundColor.Blue * 255),
-                (byte)(_backgroundColor.Alpha * 255)
-            )));
-            avatarImage.SaveAsJpeg(streamJpg);
-
-            return streamJpg.ToArray();
-        }
-
-        private void CloseButton_Pressed(object sender, EventArgs e)
-        {
-            SelectedProfileImage = null;
-
-            Close();
-        }
-
-        private void IconView_SelectionChanged(object sender, EventArgs e)
-        {
-            if (_iconView.SelectedItems.Length > 0)
-            {
-                _listStore.GetIter(out TreeIter iter, _iconView.SelectedItems[0]);
-
-                SelectedProfileImage = ProcessImage(_avatarDict[(string)_listStore.GetValue(iter, 0)]);
-            }
-        }
-
-        private void SetBackgroungColorButton_Pressed(object sender, EventArgs e)
-        {
-            using ColorChooserDialog colorChooserDialog = new("Set Background Color", this);
-
-            colorChooserDialog.UseAlpha = false;
-            colorChooserDialog.Rgba = _backgroundColor;
-
-            if (colorChooserDialog.Run() == (int)ResponseType.Ok)
-            {
-                _backgroundColor = colorChooserDialog.Rgba;
-
-                ProcessAvatars();
-            }
-
-            colorChooserDialog.Hide();
-        }
-
-        private void ChooseButton_Pressed(object sender, EventArgs e)
-        {
-            Close();
-        }
-
-        private static byte[] DecompressYaz0(Stream stream)
-        {
-            using BinaryReader reader = new(stream);
-
-            reader.ReadInt32(); // Magic
-
-            uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
-
-            reader.ReadInt64(); // Padding
-
-            byte[] input = new byte[stream.Length - stream.Position];
-            stream.Read(input, 0, input.Length);
-
-            long inputOffset = 0;
-
-            byte[] output = new byte[decodedLength];
-            long outputOffset = 0;
-
-            ushort mask = 0;
-            byte header = 0;
-
-            while (outputOffset < decodedLength)
-            {
-                if ((mask >>= 1) == 0)
-                {
-                    header = input[inputOffset++];
-                    mask = 0x80;
-                }
-
-                if ((header & mask) > 0)
-                {
-                    if (outputOffset == output.Length)
-                    {
-                        break;
-                    }
-
-                    output[outputOffset++] = input[inputOffset++];
-                }
-                else
-                {
-                    byte byte1 = input[inputOffset++];
-                    byte byte2 = input[inputOffset++];
-
-                    int dist = ((byte1 & 0xF) << 8) | byte2;
-                    int position = (int)outputOffset - (dist + 1);
-
-                    int length = byte1 >> 4;
-                    if (length == 0)
-                    {
-                        length = input[inputOffset++] + 0x12;
-                    }
-                    else
-                    {
-                        length += 2;
-                    }
-
-                    while (length-- > 0)
-                    {
-                        output[outputOffset++] = output[position++];
-                    }
-                }
-            }
-
-            return output;
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/CheatWindow.cs b/src/Ryujinx/Ui/Windows/CheatWindow.cs
deleted file mode 100644
index afccec53..00000000
--- a/src/Ryujinx/Ui/Windows/CheatWindow.cs
+++ /dev/null
@@ -1,156 +0,0 @@
-using Gtk;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
-using Ryujinx.Ui.App.Common;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using GUI = Gtk.Builder.ObjectAttribute;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class CheatWindow : Window
-    {
-        private readonly string _enabledCheatsPath;
-        private readonly bool _noCheatsFound;
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] Label _baseTitleInfoLabel;
-        [GUI] TextView _buildIdTextView;
-        [GUI] TreeView _cheatTreeView;
-        [GUI] Button _saveButton;
-#pragma warning restore CS0649, IDE0044
-
-        public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : this(new Builder("Ryujinx.Ui.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName, titlePath) { }
-
-        private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : base(builder.GetRawOwnedObject("_cheatWindow"))
-        {
-            builder.Autoconnect(this);
-            _baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
-            _buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath)}";
-
-            string modsBasePath = ModLoader.GetModsBasePath();
-            string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, titleId.ToString("X16"));
-
-            _enabledCheatsPath = System.IO.Path.Combine(titleModsPath, "cheats", "enabled.txt");
-
-            _cheatTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string), typeof(string));
-
-            CellRendererToggle enableToggle = new();
-            enableToggle.Toggled += (sender, args) =>
-            {
-                _cheatTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
-                bool newValue = !(bool)_cheatTreeView.Model.GetValue(treeIter, 0);
-                _cheatTreeView.Model.SetValue(treeIter, 0, newValue);
-
-                if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
-                {
-                    do
-                    {
-                        _cheatTreeView.Model.SetValue(childIter, 0, newValue);
-                    }
-                    while (_cheatTreeView.Model.IterNext(ref childIter));
-                }
-            };
-
-            _cheatTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
-            _cheatTreeView.AppendColumn("Name", new CellRendererText(), "text", 1);
-            _cheatTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);
-
-            var buildIdColumn = _cheatTreeView.AppendColumn("Build Id", new CellRendererText(), "text", 3);
-            buildIdColumn.Visible = false;
-
-            string[] enabled = Array.Empty<string>();
-
-            if (File.Exists(_enabledCheatsPath))
-            {
-                enabled = File.ReadAllLines(_enabledCheatsPath);
-            }
-
-            int cheatAdded = 0;
-
-            var mods = new ModLoader.ModCache();
-
-            ModLoader.QueryContentsDir(mods, new DirectoryInfo(System.IO.Path.Combine(modsBasePath, "contents")), titleId);
-
-            string currentCheatFile = string.Empty;
-            string buildId = string.Empty;
-            TreeIter parentIter = default;
-
-            foreach (var cheat in mods.Cheats)
-            {
-                if (cheat.Path.FullName != currentCheatFile)
-                {
-                    currentCheatFile = cheat.Path.FullName;
-                    string parentPath = currentCheatFile.Replace(titleModsPath, "");
-
-                    buildId = System.IO.Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
-                    parentIter = ((TreeStore)_cheatTreeView.Model).AppendValues(false, buildId, parentPath, "");
-                }
-
-                string cleanName = cheat.Name[1..^7];
-                ((TreeStore)_cheatTreeView.Model).AppendValues(parentIter, enabled.Contains($"{buildId}-{cheat.Name}"), cleanName, "", buildId);
-
-                cheatAdded++;
-            }
-
-            if (cheatAdded == 0)
-            {
-                ((TreeStore)_cheatTreeView.Model).AppendValues(false, "No Cheats Found", "", "");
-                _cheatTreeView.GetColumn(0).Visible = false;
-
-                _noCheatsFound = true;
-
-                _saveButton.Visible = false;
-            }
-
-            _cheatTreeView.ExpandAll();
-        }
-
-        private void SaveButton_Clicked(object sender, EventArgs args)
-        {
-            if (_noCheatsFound)
-            {
-                return;
-            }
-
-            List<string> enabledCheats = new();
-
-            if (_cheatTreeView.Model.GetIterFirst(out TreeIter parentIter))
-            {
-                do
-                {
-                    if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, parentIter))
-                    {
-                        do
-                        {
-                            var enabled = (bool)_cheatTreeView.Model.GetValue(childIter, 0);
-
-                            if (enabled)
-                            {
-                                var name = _cheatTreeView.Model.GetValue(childIter, 1).ToString();
-                                var buildId = _cheatTreeView.Model.GetValue(childIter, 3).ToString();
-
-                                enabledCheats.Add($"{buildId}-<{name} Cheat>");
-                            }
-                        }
-                        while (_cheatTreeView.Model.IterNext(ref childIter));
-                    }
-                }
-                while (_cheatTreeView.Model.IterNext(ref parentIter));
-            }
-
-            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(_enabledCheatsPath));
-
-            File.WriteAllLines(_enabledCheatsPath, enabledCheats);
-
-            Dispose();
-        }
-
-        private void CancelButton_Clicked(object sender, EventArgs args)
-        {
-            Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/CheatWindow.glade b/src/Ryujinx/Ui/Windows/CheatWindow.glade
deleted file mode 100644
index 9a165f1a..00000000
--- a/src/Ryujinx/Ui/Windows/CheatWindow.glade
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkWindow" id="_cheatWindow">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - Cheat Manager</property>
-    <property name="default_width">440</property>
-    <property name="default_height">550</property>
-    <child>
-      <object class="GtkBox" id="MainBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkBox" id="CheatBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkLabel" id="_baseTitleInfoLabel">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="label" translatable="yes">Available Cheats</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkTextView" id="_buildIdTextView">
-                <property name="visible">True</property>
-                <property name="margin_top">10</property>
-                <property name="halign">center</property>
-                <property name="margin_bottom">10</property>
-                <property name="editable">False</property>
-                <property name="cursor_visible">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkViewport">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkTreeView" id="_cheatTreeView">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection"/>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkButtonBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="layout_style">end</property>
-                <child>
-                  <object class="GtkButton" id="_saveButton">
-                    <property name="label" translatable="yes">Save</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_cancelButton">
-                    <property name="label" translatable="yes">Cancel</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.cs b/src/Ryujinx/Ui/Windows/ControllerWindow.cs
deleted file mode 100644
index ebf22ab6..00000000
--- a/src/Ryujinx/Ui/Windows/ControllerWindow.cs
+++ /dev/null
@@ -1,1230 +0,0 @@
-using Gtk;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller;
-using Ryujinx.Common.Configuration.Hid.Controller.Motion;
-using Ryujinx.Common.Configuration.Hid.Keyboard;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Input;
-using Ryujinx.Input.Assigner;
-using Ryujinx.Input.GTK3;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using System.Text.Json;
-using System.Threading;
-using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
-using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
-using GUI = Gtk.Builder.ObjectAttribute;
-using Key = Ryujinx.Common.Configuration.Hid.Key;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class ControllerWindow : Window
-    {
-        private readonly PlayerIndex _playerIndex;
-        private readonly InputConfig _inputConfig;
-
-        private bool _isWaitingForInput;
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] Adjustment _controllerStrongRumble;
-        [GUI] Adjustment _controllerWeakRumble;
-        [GUI] Adjustment _controllerDeadzoneLeft;
-        [GUI] Adjustment _controllerDeadzoneRight;
-        [GUI] Adjustment _controllerRangeLeft;
-        [GUI] Adjustment _controllerRangeRight;
-        [GUI] Adjustment _controllerTriggerThreshold;
-        [GUI] Adjustment _slotNumber;
-        [GUI] Adjustment _altSlotNumber;
-        [GUI] Adjustment _sensitivity;
-        [GUI] Adjustment _gyroDeadzone;
-        [GUI] CheckButton _enableMotion;
-        [GUI] CheckButton _enableCemuHook;
-        [GUI] CheckButton _mirrorInput;
-        [GUI] Entry _dsuServerHost;
-        [GUI] Entry _dsuServerPort;
-        [GUI] ComboBoxText _inputDevice;
-        [GUI] ComboBoxText _profile;
-        [GUI] Box _settingsBox;
-        [GUI] Box _motionAltBox;
-        [GUI] Box _motionBox;
-        [GUI] Box _dsuServerHostBox;
-        [GUI] Box _dsuServerPortBox;
-        [GUI] Box _motionControllerSlot;
-        [GUI] Grid _leftStickKeyboard;
-        [GUI] Grid _leftStickController;
-        [GUI] Box _deadZoneLeftBox;
-        [GUI] Box _rangeLeftBox;
-        [GUI] Grid _rightStickKeyboard;
-        [GUI] Grid _rightStickController;
-        [GUI] Box _deadZoneRightBox;
-        [GUI] Box _rangeRightBox;
-        [GUI] Grid _leftSideTriggerBox;
-        [GUI] Grid _rightSideTriggerBox;
-        [GUI] Box _triggerThresholdBox;
-        [GUI] ComboBoxText _controllerType;
-        [GUI] ToggleButton _lStick;
-        [GUI] CheckButton _invertLStickX;
-        [GUI] CheckButton _invertLStickY;
-        [GUI] CheckButton _rotateL90CW;
-        [GUI] ToggleButton _lStickUp;
-        [GUI] ToggleButton _lStickDown;
-        [GUI] ToggleButton _lStickLeft;
-        [GUI] ToggleButton _lStickRight;
-        [GUI] ToggleButton _lStickButton;
-        [GUI] ToggleButton _dpadUp;
-        [GUI] ToggleButton _dpadDown;
-        [GUI] ToggleButton _dpadLeft;
-        [GUI] ToggleButton _dpadRight;
-        [GUI] ToggleButton _minus;
-        [GUI] ToggleButton _l;
-        [GUI] ToggleButton _zL;
-        [GUI] ToggleButton _rStick;
-        [GUI] CheckButton _invertRStickX;
-        [GUI] CheckButton _invertRStickY;
-        [GUI] CheckButton _rotateR90CW;
-        [GUI] ToggleButton _rStickUp;
-        [GUI] ToggleButton _rStickDown;
-        [GUI] ToggleButton _rStickLeft;
-        [GUI] ToggleButton _rStickRight;
-        [GUI] ToggleButton _rStickButton;
-        [GUI] ToggleButton _a;
-        [GUI] ToggleButton _b;
-        [GUI] ToggleButton _x;
-        [GUI] ToggleButton _y;
-        [GUI] ToggleButton _plus;
-        [GUI] ToggleButton _r;
-        [GUI] ToggleButton _zR;
-        [GUI] ToggleButton _lSl;
-        [GUI] ToggleButton _lSr;
-        [GUI] ToggleButton _rSl;
-        [GUI] ToggleButton _rSr;
-        [GUI] Image _controllerImage;
-        [GUI] CheckButton _enableRumble;
-        [GUI] Box _rumbleBox;
-#pragma warning restore CS0649, IDE0044
-
-        private readonly MainWindow _mainWindow;
-        private readonly IGamepadDriver _gtk3KeyboardDriver;
-        private IGamepad _selectedGamepad;
-        private bool _mousePressed;
-        private bool _middleMousePressed;
-
-        private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-        public ControllerWindow(MainWindow mainWindow, PlayerIndex controllerId) : this(mainWindow, new Builder("Ryujinx.Ui.Windows.ControllerWindow.glade"), controllerId) { }
-
-        private ControllerWindow(MainWindow mainWindow, Builder builder, PlayerIndex controllerId) : base(builder.GetRawOwnedObject("_controllerWin"))
-        {
-            _mainWindow = mainWindow;
-            _selectedGamepad = null;
-
-            // NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
-            _gtk3KeyboardDriver = new GTK3KeyboardDriver(this);
-
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            builder.Autoconnect(this);
-
-            _playerIndex = controllerId;
-            _inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerIndex);
-
-            Title = $"Ryujinx - Controller Settings - {_playerIndex}";
-
-            if (_playerIndex == PlayerIndex.Handheld)
-            {
-                _controllerType.Append(ControllerType.Handheld.ToString(), "Handheld");
-                _controllerType.Sensitive = false;
-            }
-            else
-            {
-                _controllerType.Append(ControllerType.ProController.ToString(), "Pro Controller");
-                _controllerType.Append(ControllerType.JoyconPair.ToString(), "Joycon Pair");
-                _controllerType.Append(ControllerType.JoyconLeft.ToString(), "Joycon Left");
-                _controllerType.Append(ControllerType.JoyconRight.ToString(), "Joycon Right");
-            }
-
-            _controllerType.Active = 0; // Set initial value to first in list.
-
-            // Bind Events.
-            _lStick.Clicked += ButtonForStick_Pressed;
-            _lStickUp.Clicked += Button_Pressed;
-            _lStickDown.Clicked += Button_Pressed;
-            _lStickLeft.Clicked += Button_Pressed;
-            _lStickRight.Clicked += Button_Pressed;
-            _lStickButton.Clicked += Button_Pressed;
-            _dpadUp.Clicked += Button_Pressed;
-            _dpadDown.Clicked += Button_Pressed;
-            _dpadLeft.Clicked += Button_Pressed;
-            _dpadRight.Clicked += Button_Pressed;
-            _minus.Clicked += Button_Pressed;
-            _l.Clicked += Button_Pressed;
-            _zL.Clicked += Button_Pressed;
-            _lSl.Clicked += Button_Pressed;
-            _lSr.Clicked += Button_Pressed;
-            _rStick.Clicked += ButtonForStick_Pressed;
-            _rStickUp.Clicked += Button_Pressed;
-            _rStickDown.Clicked += Button_Pressed;
-            _rStickLeft.Clicked += Button_Pressed;
-            _rStickRight.Clicked += Button_Pressed;
-            _rStickButton.Clicked += Button_Pressed;
-            _a.Clicked += Button_Pressed;
-            _b.Clicked += Button_Pressed;
-            _x.Clicked += Button_Pressed;
-            _y.Clicked += Button_Pressed;
-            _plus.Clicked += Button_Pressed;
-            _r.Clicked += Button_Pressed;
-            _zR.Clicked += Button_Pressed;
-            _rSl.Clicked += Button_Pressed;
-            _rSr.Clicked += Button_Pressed;
-            _enableCemuHook.Clicked += CemuHookCheckButtonPressed;
-
-            // Setup current values.
-            UpdateInputDeviceList();
-            SetAvailableOptions();
-
-            ClearValues();
-            if (_inputDevice.ActiveId != null)
-            {
-                SetCurrentValues();
-            }
-
-            mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
-            mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
-
-            _mainWindow.RendererWidget?.NpadManager.BlockInputUpdates();
-        }
-
-        private void CemuHookCheckButtonPressed(object sender, EventArgs e)
-        {
-            UpdateCemuHookSpecificFieldsVisibility();
-        }
-
-        private void HandleOnGamepadDisconnected(string id)
-        {
-            Application.Invoke(delegate
-            {
-                UpdateInputDeviceList();
-            });
-        }
-
-        private void HandleOnGamepadConnected(string id)
-        {
-            Application.Invoke(delegate
-            {
-                UpdateInputDeviceList();
-            });
-        }
-
-        protected override void OnDestroyed()
-        {
-            _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
-            _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
-
-            _mainWindow.RendererWidget?.NpadManager.UnblockInputUpdates();
-
-            _selectedGamepad?.Dispose();
-
-            _gtk3KeyboardDriver.Dispose();
-        }
-
-        private static string GetShortGamepadName(string str)
-        {
-            const string ShrinkChars = "...";
-            const int MaxSize = 50;
-
-            if (str.Length > MaxSize)
-            {
-                return $"{str.AsSpan(0, MaxSize - ShrinkChars.Length)}{ShrinkChars}";
-            }
-
-            return str;
-        }
-
-        private void UpdateInputDeviceList()
-        {
-            _inputDevice.RemoveAll();
-            _inputDevice.Append("disabled", "Disabled");
-            _inputDevice.SetActiveId("disabled");
-
-            foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
-            {
-                IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
-
-                if (gamepad != null)
-                {
-                    _inputDevice.Append($"keyboard/{id}", GetShortGamepadName($"{gamepad.Name} ({id})"));
-
-                    gamepad.Dispose();
-                }
-            }
-
-            foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
-            {
-                IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
-
-                if (gamepad != null)
-                {
-                    _inputDevice.Append($"controller/{id}", GetShortGamepadName($"{gamepad.Name} ({id})"));
-
-                    gamepad.Dispose();
-                }
-            }
-
-            switch (_inputConfig)
-            {
-                case StandardKeyboardInputConfig keyboard:
-                    _inputDevice.SetActiveId($"keyboard/{keyboard.Id}");
-                    break;
-                case StandardControllerInputConfig controller:
-                    _inputDevice.SetActiveId($"controller/{controller.Id}");
-                    break;
-            }
-        }
-
-        private void UpdateCemuHookSpecificFieldsVisibility()
-        {
-            if (_enableCemuHook.Active)
-            {
-                _dsuServerHostBox.Show();
-                _dsuServerPortBox.Show();
-                _motionControllerSlot.Show();
-                _motionAltBox.Show();
-                _mirrorInput.Show();
-            }
-            else
-            {
-                _dsuServerHostBox.Hide();
-                _dsuServerPortBox.Hide();
-                _motionControllerSlot.Hide();
-                _motionAltBox.Hide();
-                _mirrorInput.Hide();
-            }
-        }
-
-        private void SetAvailableOptions()
-        {
-            if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("keyboard"))
-            {
-                ShowAll();
-                _leftStickController.Hide();
-                _rightStickController.Hide();
-                _deadZoneLeftBox.Hide();
-                _deadZoneRightBox.Hide();
-                _rangeLeftBox.Hide();
-                _rangeRightBox.Hide();
-                _triggerThresholdBox.Hide();
-                _motionBox.Hide();
-                _rumbleBox.Hide();
-            }
-            else if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("controller"))
-            {
-                ShowAll();
-                _leftStickKeyboard.Hide();
-                _rightStickKeyboard.Hide();
-
-                UpdateCemuHookSpecificFieldsVisibility();
-            }
-            else
-            {
-                _settingsBox.Hide();
-            }
-
-            ClearValues();
-        }
-
-        private void SetCurrentValues()
-        {
-            SetControllerSpecificFields();
-
-            SetProfiles();
-
-            if (_inputDevice.ActiveId.StartsWith("keyboard") && _inputConfig is StandardKeyboardInputConfig)
-            {
-                SetValues(_inputConfig);
-            }
-            else if (_inputDevice.ActiveId.StartsWith("controller") && _inputConfig is StandardControllerInputConfig)
-            {
-                SetValues(_inputConfig);
-            }
-        }
-
-        private void SetControllerSpecificFields()
-        {
-            _leftSideTriggerBox.Hide();
-            _rightSideTriggerBox.Hide();
-            _motionAltBox.Hide();
-
-            switch (_controllerType.ActiveId)
-            {
-                case "JoyconLeft":
-                    _leftSideTriggerBox.Show();
-                    break;
-                case "JoyconRight":
-                    _rightSideTriggerBox.Show();
-                    break;
-                case "JoyconPair":
-                    _motionAltBox.Show();
-                    break;
-            }
-
-            if (!OperatingSystem.IsMacOS())
-            {
-                _controllerImage.Pixbuf = _controllerType.ActiveId switch
-                {
-                    "ProController" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_ProCon.svg", 400, 400),
-                    "JoyconLeft" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConLeft.svg", 400, 500),
-                    "JoyconRight" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConRight.svg", 400, 500),
-                    _ => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConPair.svg", 400, 500),
-                };
-            }
-        }
-
-        private void ClearValues()
-        {
-            _lStick.Label = "Unbound";
-            _lStickUp.Label = "Unbound";
-            _lStickDown.Label = "Unbound";
-            _lStickLeft.Label = "Unbound";
-            _lStickRight.Label = "Unbound";
-            _lStickButton.Label = "Unbound";
-            _dpadUp.Label = "Unbound";
-            _dpadDown.Label = "Unbound";
-            _dpadLeft.Label = "Unbound";
-            _dpadRight.Label = "Unbound";
-            _minus.Label = "Unbound";
-            _l.Label = "Unbound";
-            _zL.Label = "Unbound";
-            _lSl.Label = "Unbound";
-            _lSr.Label = "Unbound";
-            _rStick.Label = "Unbound";
-            _rStickUp.Label = "Unbound";
-            _rStickDown.Label = "Unbound";
-            _rStickLeft.Label = "Unbound";
-            _rStickRight.Label = "Unbound";
-            _rStickButton.Label = "Unbound";
-            _a.Label = "Unbound";
-            _b.Label = "Unbound";
-            _x.Label = "Unbound";
-            _y.Label = "Unbound";
-            _plus.Label = "Unbound";
-            _r.Label = "Unbound";
-            _zR.Label = "Unbound";
-            _rSl.Label = "Unbound";
-            _rSr.Label = "Unbound";
-            _controllerStrongRumble.Value = 1;
-            _controllerWeakRumble.Value = 1;
-            _controllerDeadzoneLeft.Value = 0;
-            _controllerDeadzoneRight.Value = 0;
-            _controllerRangeLeft.Value = 1;
-            _controllerRangeRight.Value = 1;
-            _controllerTriggerThreshold.Value = 0;
-            _mirrorInput.Active = false;
-            _enableMotion.Active = false;
-            _enableCemuHook.Active = false;
-            _slotNumber.Value = 0;
-            _altSlotNumber.Value = 0;
-            _sensitivity.Value = 100;
-            _gyroDeadzone.Value = 1;
-            _dsuServerHost.Buffer.Text = "";
-            _dsuServerPort.Buffer.Text = "";
-            _enableRumble.Active = false;
-        }
-
-        private void SetValues(InputConfig config)
-        {
-            switch (config)
-            {
-                case StandardKeyboardInputConfig keyboardConfig:
-                    if (!_controllerType.SetActiveId(keyboardConfig.ControllerType.ToString()))
-                    {
-                        _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
-                            ? ControllerType.Handheld.ToString()
-                            : ControllerType.ProController.ToString());
-                    }
-
-                    _lStickUp.Label = keyboardConfig.LeftJoyconStick.StickUp.ToString();
-                    _lStickDown.Label = keyboardConfig.LeftJoyconStick.StickDown.ToString();
-                    _lStickLeft.Label = keyboardConfig.LeftJoyconStick.StickLeft.ToString();
-                    _lStickRight.Label = keyboardConfig.LeftJoyconStick.StickRight.ToString();
-                    _lStickButton.Label = keyboardConfig.LeftJoyconStick.StickButton.ToString();
-                    _dpadUp.Label = keyboardConfig.LeftJoycon.DpadUp.ToString();
-                    _dpadDown.Label = keyboardConfig.LeftJoycon.DpadDown.ToString();
-                    _dpadLeft.Label = keyboardConfig.LeftJoycon.DpadLeft.ToString();
-                    _dpadRight.Label = keyboardConfig.LeftJoycon.DpadRight.ToString();
-                    _minus.Label = keyboardConfig.LeftJoycon.ButtonMinus.ToString();
-                    _l.Label = keyboardConfig.LeftJoycon.ButtonL.ToString();
-                    _zL.Label = keyboardConfig.LeftJoycon.ButtonZl.ToString();
-                    _lSl.Label = keyboardConfig.LeftJoycon.ButtonSl.ToString();
-                    _lSr.Label = keyboardConfig.LeftJoycon.ButtonSr.ToString();
-                    _rStickUp.Label = keyboardConfig.RightJoyconStick.StickUp.ToString();
-                    _rStickDown.Label = keyboardConfig.RightJoyconStick.StickDown.ToString();
-                    _rStickLeft.Label = keyboardConfig.RightJoyconStick.StickLeft.ToString();
-                    _rStickRight.Label = keyboardConfig.RightJoyconStick.StickRight.ToString();
-                    _rStickButton.Label = keyboardConfig.RightJoyconStick.StickButton.ToString();
-                    _a.Label = keyboardConfig.RightJoycon.ButtonA.ToString();
-                    _b.Label = keyboardConfig.RightJoycon.ButtonB.ToString();
-                    _x.Label = keyboardConfig.RightJoycon.ButtonX.ToString();
-                    _y.Label = keyboardConfig.RightJoycon.ButtonY.ToString();
-                    _plus.Label = keyboardConfig.RightJoycon.ButtonPlus.ToString();
-                    _r.Label = keyboardConfig.RightJoycon.ButtonR.ToString();
-                    _zR.Label = keyboardConfig.RightJoycon.ButtonZr.ToString();
-                    _rSl.Label = keyboardConfig.RightJoycon.ButtonSl.ToString();
-                    _rSr.Label = keyboardConfig.RightJoycon.ButtonSr.ToString();
-                    break;
-
-                case StandardControllerInputConfig controllerConfig:
-                    if (!_controllerType.SetActiveId(controllerConfig.ControllerType.ToString()))
-                    {
-                        _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
-                            ? ControllerType.Handheld.ToString()
-                            : ControllerType.ProController.ToString());
-                    }
-
-                    _lStick.Label = controllerConfig.LeftJoyconStick.Joystick.ToString();
-                    _invertLStickX.Active = controllerConfig.LeftJoyconStick.InvertStickX;
-                    _invertLStickY.Active = controllerConfig.LeftJoyconStick.InvertStickY;
-                    _rotateL90CW.Active = controllerConfig.LeftJoyconStick.Rotate90CW;
-                    _lStickButton.Label = controllerConfig.LeftJoyconStick.StickButton.ToString();
-                    _dpadUp.Label = controllerConfig.LeftJoycon.DpadUp.ToString();
-                    _dpadDown.Label = controllerConfig.LeftJoycon.DpadDown.ToString();
-                    _dpadLeft.Label = controllerConfig.LeftJoycon.DpadLeft.ToString();
-                    _dpadRight.Label = controllerConfig.LeftJoycon.DpadRight.ToString();
-                    _minus.Label = controllerConfig.LeftJoycon.ButtonMinus.ToString();
-                    _l.Label = controllerConfig.LeftJoycon.ButtonL.ToString();
-                    _zL.Label = controllerConfig.LeftJoycon.ButtonZl.ToString();
-                    _lSl.Label = controllerConfig.LeftJoycon.ButtonSl.ToString();
-                    _lSr.Label = controllerConfig.LeftJoycon.ButtonSr.ToString();
-                    _rStick.Label = controllerConfig.RightJoyconStick.Joystick.ToString();
-                    _invertRStickX.Active = controllerConfig.RightJoyconStick.InvertStickX;
-                    _invertRStickY.Active = controllerConfig.RightJoyconStick.InvertStickY;
-                    _rotateR90CW.Active = controllerConfig.RightJoyconStick.Rotate90CW;
-                    _rStickButton.Label = controllerConfig.RightJoyconStick.StickButton.ToString();
-                    _a.Label = controllerConfig.RightJoycon.ButtonA.ToString();
-                    _b.Label = controllerConfig.RightJoycon.ButtonB.ToString();
-                    _x.Label = controllerConfig.RightJoycon.ButtonX.ToString();
-                    _y.Label = controllerConfig.RightJoycon.ButtonY.ToString();
-                    _plus.Label = controllerConfig.RightJoycon.ButtonPlus.ToString();
-                    _r.Label = controllerConfig.RightJoycon.ButtonR.ToString();
-                    _zR.Label = controllerConfig.RightJoycon.ButtonZr.ToString();
-                    _rSl.Label = controllerConfig.RightJoycon.ButtonSl.ToString();
-                    _rSr.Label = controllerConfig.RightJoycon.ButtonSr.ToString();
-                    _controllerStrongRumble.Value = controllerConfig.Rumble.StrongRumble;
-                    _controllerWeakRumble.Value = controllerConfig.Rumble.WeakRumble;
-                    _enableRumble.Active = controllerConfig.Rumble.EnableRumble;
-                    _controllerDeadzoneLeft.Value = controllerConfig.DeadzoneLeft;
-                    _controllerDeadzoneRight.Value = controllerConfig.DeadzoneRight;
-                    _controllerRangeLeft.Value = controllerConfig.RangeLeft;
-                    _controllerRangeRight.Value = controllerConfig.RangeRight;
-                    _controllerTriggerThreshold.Value = controllerConfig.TriggerThreshold;
-                    _sensitivity.Value = controllerConfig.Motion.Sensitivity;
-                    _gyroDeadzone.Value = controllerConfig.Motion.GyroDeadzone;
-                    _enableMotion.Active = controllerConfig.Motion.EnableMotion;
-                    _enableCemuHook.Active = controllerConfig.Motion.MotionBackend == MotionInputBackendType.CemuHook;
-
-                    // If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
-                    if (_controllerRangeLeft.Value <= 0.0 && _controllerRangeRight.Value <= 0.0)
-                    {
-                        _controllerRangeLeft.Value = 1.0;
-                        _controllerRangeRight.Value = 1.0;
-
-                        Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
-                    }
-
-                    if (controllerConfig.Motion is CemuHookMotionConfigController cemuHookMotionConfig)
-                    {
-                        _slotNumber.Value = cemuHookMotionConfig.Slot;
-                        _altSlotNumber.Value = cemuHookMotionConfig.AltSlot;
-                        _mirrorInput.Active = cemuHookMotionConfig.MirrorInput;
-                        _dsuServerHost.Buffer.Text = cemuHookMotionConfig.DsuServerHost;
-                        _dsuServerPort.Buffer.Text = cemuHookMotionConfig.DsuServerPort.ToString();
-                    }
-
-                    break;
-            }
-        }
-
-        private InputConfig GetValues()
-        {
-            if (_inputDevice.ActiveId.StartsWith("keyboard"))
-            {
-#pragma warning disable CA1806, IDE0055 // Disable formatting
-                Enum.TryParse(_lStickUp.Label,     out Key lStickUp);
-                Enum.TryParse(_lStickDown.Label,   out Key lStickDown);
-                Enum.TryParse(_lStickLeft.Label,   out Key lStickLeft);
-                Enum.TryParse(_lStickRight.Label,  out Key lStickRight);
-                Enum.TryParse(_lStickButton.Label, out Key lStickButton);
-                Enum.TryParse(_dpadUp.Label,       out Key lDPadUp);
-                Enum.TryParse(_dpadDown.Label,     out Key lDPadDown);
-                Enum.TryParse(_dpadLeft.Label,     out Key lDPadLeft);
-                Enum.TryParse(_dpadRight.Label,    out Key lDPadRight);
-                Enum.TryParse(_minus.Label,        out Key lButtonMinus);
-                Enum.TryParse(_l.Label,            out Key lButtonL);
-                Enum.TryParse(_zL.Label,           out Key lButtonZl);
-                Enum.TryParse(_lSl.Label,          out Key lButtonSl);
-                Enum.TryParse(_lSr.Label,          out Key lButtonSr);
-
-                Enum.TryParse(_rStickUp.Label,     out Key rStickUp);
-                Enum.TryParse(_rStickDown.Label,   out Key rStickDown);
-                Enum.TryParse(_rStickLeft.Label,   out Key rStickLeft);
-                Enum.TryParse(_rStickRight.Label,  out Key rStickRight);
-                Enum.TryParse(_rStickButton.Label, out Key rStickButton);
-                Enum.TryParse(_a.Label,            out Key rButtonA);
-                Enum.TryParse(_b.Label,            out Key rButtonB);
-                Enum.TryParse(_x.Label,            out Key rButtonX);
-                Enum.TryParse(_y.Label,            out Key rButtonY);
-                Enum.TryParse(_plus.Label,         out Key rButtonPlus);
-                Enum.TryParse(_r.Label,            out Key rButtonR);
-                Enum.TryParse(_zR.Label,           out Key rButtonZr);
-                Enum.TryParse(_rSl.Label,          out Key rButtonSl);
-                Enum.TryParse(_rSr.Label,          out Key rButtonSr);
-#pragma warning restore CA1806, IDE0055
-
-                return new StandardKeyboardInputConfig
-                {
-                    Backend = InputBackendType.WindowKeyboard,
-                    Version = InputConfig.CurrentVersion,
-                    Id = _inputDevice.ActiveId.Split("/")[1],
-                    ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId),
-                    PlayerIndex = _playerIndex,
-                    LeftJoycon = new LeftJoyconCommonConfig<Key>
-                    {
-                        ButtonMinus = lButtonMinus,
-                        ButtonL = lButtonL,
-                        ButtonZl = lButtonZl,
-                        ButtonSl = lButtonSl,
-                        ButtonSr = lButtonSr,
-                        DpadUp = lDPadUp,
-                        DpadDown = lDPadDown,
-                        DpadLeft = lDPadLeft,
-                        DpadRight = lDPadRight,
-                    },
-                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
-                    {
-                        StickUp = lStickUp,
-                        StickDown = lStickDown,
-                        StickLeft = lStickLeft,
-                        StickRight = lStickRight,
-                        StickButton = lStickButton,
-                    },
-                    RightJoycon = new RightJoyconCommonConfig<Key>
-                    {
-                        ButtonA = rButtonA,
-                        ButtonB = rButtonB,
-                        ButtonX = rButtonX,
-                        ButtonY = rButtonY,
-                        ButtonPlus = rButtonPlus,
-                        ButtonR = rButtonR,
-                        ButtonZr = rButtonZr,
-                        ButtonSl = rButtonSl,
-                        ButtonSr = rButtonSr,
-                    },
-                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                    {
-                        StickUp = rStickUp,
-                        StickDown = rStickDown,
-                        StickLeft = rStickLeft,
-                        StickRight = rStickRight,
-                        StickButton = rStickButton,
-                    },
-                };
-            }
-
-            if (_inputDevice.ActiveId.StartsWith("controller"))
-            {
-#pragma warning disable CA1806, IDE0055 // Disable formatting
-                Enum.TryParse(_lStick.Label,       out ConfigStickInputId   lStick);
-                Enum.TryParse(_lStickButton.Label, out ConfigGamepadInputId lStickButton);
-                Enum.TryParse(_minus.Label,        out ConfigGamepadInputId lButtonMinus);
-                Enum.TryParse(_l.Label,            out ConfigGamepadInputId lButtonL);
-                Enum.TryParse(_zL.Label,           out ConfigGamepadInputId lButtonZl);
-                Enum.TryParse(_lSl.Label,          out ConfigGamepadInputId lButtonSl);
-                Enum.TryParse(_lSr.Label,          out ConfigGamepadInputId lButtonSr);
-                Enum.TryParse(_dpadUp.Label,       out ConfigGamepadInputId lDPadUp);
-                Enum.TryParse(_dpadDown.Label,     out ConfigGamepadInputId lDPadDown);
-                Enum.TryParse(_dpadLeft.Label,     out ConfigGamepadInputId lDPadLeft);
-                Enum.TryParse(_dpadRight.Label,    out ConfigGamepadInputId lDPadRight);
-
-                Enum.TryParse(_rStick.Label,       out ConfigStickInputId   rStick);
-                Enum.TryParse(_rStickButton.Label, out ConfigGamepadInputId rStickButton);
-                Enum.TryParse(_a.Label,            out ConfigGamepadInputId rButtonA);
-                Enum.TryParse(_b.Label,            out ConfigGamepadInputId rButtonB);
-                Enum.TryParse(_x.Label,            out ConfigGamepadInputId rButtonX);
-                Enum.TryParse(_y.Label,            out ConfigGamepadInputId rButtonY);
-                Enum.TryParse(_plus.Label,         out ConfigGamepadInputId rButtonPlus);
-                Enum.TryParse(_r.Label,            out ConfigGamepadInputId rButtonR);
-                Enum.TryParse(_zR.Label,           out ConfigGamepadInputId rButtonZr);
-                Enum.TryParse(_rSl.Label,          out ConfigGamepadInputId rButtonSl);
-                Enum.TryParse(_rSr.Label,          out ConfigGamepadInputId rButtonSr);
-
-                int.TryParse(_dsuServerPort.Buffer.Text, out int port);
-#pragma warning restore CA1806, IDE0055
-
-                MotionConfigController motionConfig;
-
-                if (_enableCemuHook.Active)
-                {
-                    motionConfig = new CemuHookMotionConfigController
-                    {
-                        MotionBackend = MotionInputBackendType.CemuHook,
-                        EnableMotion = _enableMotion.Active,
-                        Sensitivity = (int)_sensitivity.Value,
-                        GyroDeadzone = _gyroDeadzone.Value,
-                        MirrorInput = _mirrorInput.Active,
-                        Slot = (int)_slotNumber.Value,
-                        AltSlot = (int)_altSlotNumber.Value,
-                        DsuServerHost = _dsuServerHost.Buffer.Text,
-                        DsuServerPort = port,
-                    };
-                }
-                else
-                {
-                    motionConfig = new StandardMotionConfigController
-                    {
-                        MotionBackend = MotionInputBackendType.GamepadDriver,
-                        EnableMotion = _enableMotion.Active,
-                        Sensitivity = (int)_sensitivity.Value,
-                        GyroDeadzone = _gyroDeadzone.Value,
-                    };
-                }
-
-                return new StandardControllerInputConfig
-                {
-                    Backend = InputBackendType.GamepadSDL2,
-                    Version = InputConfig.CurrentVersion,
-                    Id = _inputDevice.ActiveId.Split("/")[1].Split(" ")[0],
-                    ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId),
-                    PlayerIndex = _playerIndex,
-                    DeadzoneLeft = (float)_controllerDeadzoneLeft.Value,
-                    DeadzoneRight = (float)_controllerDeadzoneRight.Value,
-                    RangeLeft = (float)_controllerRangeLeft.Value,
-                    RangeRight = (float)_controllerRangeRight.Value,
-                    TriggerThreshold = (float)_controllerTriggerThreshold.Value,
-                    LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
-                    {
-                        ButtonMinus = lButtonMinus,
-                        ButtonL = lButtonL,
-                        ButtonZl = lButtonZl,
-                        ButtonSl = lButtonSl,
-                        ButtonSr = lButtonSr,
-                        DpadUp = lDPadUp,
-                        DpadDown = lDPadDown,
-                        DpadLeft = lDPadLeft,
-                        DpadRight = lDPadRight,
-                    },
-                    LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                    {
-                        InvertStickX = _invertLStickX.Active,
-                        Joystick = lStick,
-                        InvertStickY = _invertLStickY.Active,
-                        StickButton = lStickButton,
-                        Rotate90CW = _rotateL90CW.Active,
-                    },
-                    RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
-                    {
-                        ButtonA = rButtonA,
-                        ButtonB = rButtonB,
-                        ButtonX = rButtonX,
-                        ButtonY = rButtonY,
-                        ButtonPlus = rButtonPlus,
-                        ButtonR = rButtonR,
-                        ButtonZr = rButtonZr,
-                        ButtonSl = rButtonSl,
-                        ButtonSr = rButtonSr,
-                    },
-                    RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                    {
-                        InvertStickX = _invertRStickX.Active,
-                        Joystick = rStick,
-                        InvertStickY = _invertRStickY.Active,
-                        StickButton = rStickButton,
-                        Rotate90CW = _rotateR90CW.Active,
-                    },
-                    Motion = motionConfig,
-                    Rumble = new RumbleConfigController
-                    {
-                        StrongRumble = (float)_controllerStrongRumble.Value,
-                        WeakRumble = (float)_controllerWeakRumble.Value,
-                        EnableRumble = _enableRumble.Active,
-                    },
-                };
-            }
-
-            if (!_inputDevice.ActiveId.StartsWith("disabled"))
-            {
-                GtkDialog.CreateErrorDialog("Invalid data detected in one or more fields; the configuration was not saved.");
-            }
-
-            return null;
-        }
-
-        private string GetProfileBasePath()
-        {
-            if (_inputDevice.ActiveId.StartsWith("keyboard"))
-            {
-                return System.IO.Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
-            }
-            else if (_inputDevice.ActiveId.StartsWith("controller"))
-            {
-                return System.IO.Path.Combine(AppDataManager.ProfilesDirPath, "controller");
-            }
-
-            return AppDataManager.ProfilesDirPath;
-        }
-
-        //
-        // Events
-        //
-        private void InputDevice_Changed(object sender, EventArgs args)
-        {
-            SetAvailableOptions();
-            SetControllerSpecificFields();
-
-            _selectedGamepad?.Dispose();
-            _selectedGamepad = null;
-
-            if (_inputDevice.ActiveId != null)
-            {
-                SetProfiles();
-
-                string id = GetCurrentGamepadId();
-
-                if (_inputDevice.ActiveId.StartsWith("keyboard"))
-                {
-                    if (_inputConfig is StandardKeyboardInputConfig)
-                    {
-                        SetValues(_inputConfig);
-                    }
-
-                    if (_mainWindow.InputManager.KeyboardDriver is GTK3KeyboardDriver)
-                    {
-                        // NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
-                        _selectedGamepad = _gtk3KeyboardDriver.GetGamepad(id);
-                    }
-                    else
-                    {
-                        _selectedGamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
-                    }
-                }
-                else if (_inputDevice.ActiveId.StartsWith("controller"))
-                {
-                    if (_inputConfig is StandardControllerInputConfig)
-                    {
-                        SetValues(_inputConfig);
-                    }
-
-                    _selectedGamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
-                }
-            }
-        }
-
-        private string GetCurrentGamepadId()
-        {
-            if (_inputDevice.ActiveId == null || _inputDevice.ActiveId == "disabled")
-            {
-                return null;
-            }
-
-            return _inputDevice.ActiveId.Split("/")[1].Split(" ")[0];
-        }
-
-        private void Controller_Changed(object sender, EventArgs args)
-        {
-            SetControllerSpecificFields();
-        }
-
-        private IButtonAssigner CreateButtonAssigner(bool forStick)
-        {
-            IButtonAssigner assigner;
-
-            if (_inputDevice.ActiveId.StartsWith("keyboard"))
-            {
-                assigner = new KeyboardKeyAssigner((IKeyboard)_selectedGamepad);
-            }
-            else if (_inputDevice.ActiveId.StartsWith("controller"))
-            {
-                assigner = new GamepadButtonAssigner(_selectedGamepad, (float)_controllerTriggerThreshold.Value, forStick);
-            }
-            else
-            {
-                throw new Exception("Controller not supported");
-            }
-
-            return assigner;
-        }
-
-        private void HandleButtonPressed(ToggleButton button, bool forStick)
-        {
-            if (_isWaitingForInput)
-            {
-                button.Active = false;
-
-                return;
-            }
-
-            _mousePressed = false;
-
-            ButtonPressEvent += MouseClick;
-
-            IButtonAssigner assigner = CreateButtonAssigner(forStick);
-
-            _isWaitingForInput = true;
-
-            // Open GTK3 keyboard for cancel operations
-            IKeyboard keyboard = (IKeyboard)_gtk3KeyboardDriver.GetGamepad("0");
-
-            Thread inputThread = new(() =>
-            {
-                assigner.Initialize();
-
-                while (true)
-                {
-                    Thread.Sleep(10);
-                    assigner.ReadInput();
-
-                    if (_mousePressed || keyboard.IsPressed(Ryujinx.Input.Key.Escape) || assigner.HasAnyButtonPressed() || assigner.ShouldCancel())
-                    {
-                        break;
-                    }
-                }
-
-                string pressedButton = assigner.GetPressedButton();
-
-                Application.Invoke(delegate
-                {
-                    if (_middleMousePressed)
-                    {
-                        button.Label = "Unbound";
-                    }
-                    else if (pressedButton != "")
-                    {
-                        button.Label = pressedButton;
-                    }
-
-                    _middleMousePressed = false;
-
-                    ButtonPressEvent -= MouseClick;
-                    keyboard.Dispose();
-
-                    button.Active = false;
-                    _isWaitingForInput = false;
-                });
-            })
-            {
-                Name = "GUI.InputThread",
-                IsBackground = true,
-            };
-            inputThread.Start();
-        }
-
-        private void Button_Pressed(object sender, EventArgs args)
-        {
-            HandleButtonPressed((ToggleButton)sender, false);
-        }
-
-        private void ButtonForStick_Pressed(object sender, EventArgs args)
-        {
-            HandleButtonPressed((ToggleButton)sender, true);
-        }
-
-        private void MouseClick(object sender, ButtonPressEventArgs args)
-        {
-            _mousePressed = true;
-            _middleMousePressed = args.Event.Button == 2;
-        }
-
-        private void SetProfiles()
-        {
-            _profile.RemoveAll();
-
-            string basePath = GetProfileBasePath();
-
-            if (!Directory.Exists(basePath))
-            {
-                Directory.CreateDirectory(basePath);
-            }
-
-            if (_inputDevice.ActiveId == null || _inputDevice.ActiveId.Equals("disabled"))
-            {
-                _profile.Append("default", "None");
-            }
-            else
-            {
-                _profile.Append("default", "Default");
-
-                foreach (string profile in Directory.GetFiles(basePath, "*.*", SearchOption.AllDirectories))
-                {
-                    _profile.Append(System.IO.Path.GetFileName(profile), System.IO.Path.GetFileNameWithoutExtension(profile));
-                }
-            }
-
-            _profile.SetActiveId("default");
-        }
-
-        private void ProfileLoad_Activated(object sender, EventArgs args)
-        {
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-
-            if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == null)
-            {
-                return;
-            }
-
-            InputConfig config = null;
-            int pos = _profile.Active;
-
-            if (_profile.ActiveId == "default")
-            {
-                if (_inputDevice.ActiveId.StartsWith("keyboard"))
-                {
-                    config = new StandardKeyboardInputConfig
-                    {
-                        Version = InputConfig.CurrentVersion,
-                        Backend = InputBackendType.WindowKeyboard,
-                        Id = null,
-                        ControllerType = ControllerType.ProController,
-                        LeftJoycon = new LeftJoyconCommonConfig<Key>
-                        {
-                            DpadUp = Key.Up,
-                            DpadDown = Key.Down,
-                            DpadLeft = Key.Left,
-                            DpadRight = Key.Right,
-                            ButtonMinus = Key.Minus,
-                            ButtonL = Key.E,
-                            ButtonZl = Key.Q,
-                            ButtonSl = Key.Unbound,
-                            ButtonSr = Key.Unbound,
-                        },
-
-                        LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
-                        {
-                            StickUp = Key.W,
-                            StickDown = Key.S,
-                            StickLeft = Key.A,
-                            StickRight = Key.D,
-                            StickButton = Key.F,
-                        },
-
-                        RightJoycon = new RightJoyconCommonConfig<Key>
-                        {
-                            ButtonA = Key.Z,
-                            ButtonB = Key.X,
-                            ButtonX = Key.C,
-                            ButtonY = Key.V,
-                            ButtonPlus = Key.Plus,
-                            ButtonR = Key.U,
-                            ButtonZr = Key.O,
-                            ButtonSl = Key.Unbound,
-                            ButtonSr = Key.Unbound,
-                        },
-
-                        RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                        {
-                            StickUp = Key.I,
-                            StickDown = Key.K,
-                            StickLeft = Key.J,
-                            StickRight = Key.L,
-                            StickButton = Key.H,
-                        },
-                    };
-                }
-                else if (_inputDevice.ActiveId.StartsWith("controller"))
-                {
-                    bool isNintendoStyle = _inputDevice.ActiveText.Contains("Nintendo");
-
-                    config = new StandardControllerInputConfig
-                    {
-                        Version = InputConfig.CurrentVersion,
-                        Backend = InputBackendType.GamepadSDL2,
-                        Id = null,
-                        ControllerType = ControllerType.JoyconPair,
-                        DeadzoneLeft = 0.1f,
-                        DeadzoneRight = 0.1f,
-                        RangeLeft = 1.0f,
-                        RangeRight = 1.0f,
-                        TriggerThreshold = 0.5f,
-                        LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
-                        {
-                            DpadUp = ConfigGamepadInputId.DpadUp,
-                            DpadDown = ConfigGamepadInputId.DpadDown,
-                            DpadLeft = ConfigGamepadInputId.DpadLeft,
-                            DpadRight = ConfigGamepadInputId.DpadRight,
-                            ButtonMinus = ConfigGamepadInputId.Minus,
-                            ButtonL = ConfigGamepadInputId.LeftShoulder,
-                            ButtonZl = ConfigGamepadInputId.LeftTrigger,
-                            ButtonSl = ConfigGamepadInputId.Unbound,
-                            ButtonSr = ConfigGamepadInputId.Unbound,
-                        },
-
-                        LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                        {
-                            Joystick = ConfigStickInputId.Left,
-                            StickButton = ConfigGamepadInputId.LeftStick,
-                            InvertStickX = false,
-                            InvertStickY = false,
-                            Rotate90CW = false,
-                        },
-
-                        RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
-                        {
-                            ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
-                            ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
-                            ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
-                            ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
-                            ButtonPlus = ConfigGamepadInputId.Plus,
-                            ButtonR = ConfigGamepadInputId.RightShoulder,
-                            ButtonZr = ConfigGamepadInputId.RightTrigger,
-                            ButtonSl = ConfigGamepadInputId.Unbound,
-                            ButtonSr = ConfigGamepadInputId.Unbound,
-                        },
-
-                        RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                        {
-                            Joystick = ConfigStickInputId.Right,
-                            StickButton = ConfigGamepadInputId.RightStick,
-                            InvertStickX = false,
-                            InvertStickY = false,
-                            Rotate90CW = false,
-                        },
-
-                        Motion = new StandardMotionConfigController
-                        {
-                            MotionBackend = MotionInputBackendType.GamepadDriver,
-                            EnableMotion = true,
-                            Sensitivity = 100,
-                            GyroDeadzone = 1,
-                        },
-                        Rumble = new RumbleConfigController
-                        {
-                            StrongRumble = 1f,
-                            WeakRumble = 1f,
-                            EnableRumble = false,
-                        },
-                    };
-                }
-            }
-            else
-            {
-                string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId);
-
-                if (!File.Exists(path))
-                {
-                    if (pos >= 0)
-                    {
-                        _profile.Remove(pos);
-                    }
-
-                    return;
-                }
-
-                try
-                {
-                    config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
-                }
-                catch (JsonException) { }
-            }
-
-            SetValues(config);
-        }
-
-        private void ProfileAdd_Activated(object sender, EventArgs args)
-        {
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-
-            if (_inputDevice.ActiveId == "disabled")
-            {
-                return;
-            }
-
-            InputConfig inputConfig = GetValues();
-            ProfileDialog profileDialog = new();
-
-            if (inputConfig == null)
-            {
-                return;
-            }
-
-            if (profileDialog.Run() == (int)ResponseType.Ok)
-            {
-                string path = System.IO.Path.Combine(GetProfileBasePath(), profileDialog.FileName);
-                string jsonString = JsonHelper.Serialize(inputConfig, _serializerContext.InputConfig);
-
-                File.WriteAllText(path, jsonString);
-            }
-
-            profileDialog.Dispose();
-
-            SetProfiles();
-        }
-
-        private void ProfileRemove_Activated(object sender, EventArgs args)
-        {
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-
-            if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == "default" || _profile.ActiveId == null)
-            {
-                return;
-            }
-
-            MessageDialog confirmDialog = GtkDialog.CreateConfirmationDialog("Deleting Profile", "This action is irreversible, are you sure you want to continue?");
-
-            if (confirmDialog.Run() == (int)ResponseType.Yes)
-            {
-                string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId);
-
-                if (File.Exists(path))
-                {
-                    File.Delete(path);
-                }
-
-                SetProfiles();
-            }
-        }
-
-        private void SaveToggle_Activated(object sender, EventArgs args)
-        {
-            InputConfig inputConfig = GetValues();
-
-            var newConfig = new List<InputConfig>();
-            newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
-
-            if (_inputConfig == null && inputConfig != null)
-            {
-                newConfig.Add(inputConfig);
-            }
-            else
-            {
-                if (_inputDevice.ActiveId == "disabled")
-                {
-                    newConfig.Remove(_inputConfig);
-                }
-                else if (inputConfig != null)
-                {
-                    int index = newConfig.IndexOf(_inputConfig);
-
-                    newConfig[index] = inputConfig;
-                }
-            }
-
-            _mainWindow.RendererWidget?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
-
-            // Atomically replace and signal input change.
-            // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
-            ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
-
-            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-
-            Dispose();
-        }
-
-        private void CloseToggle_Activated(object sender, EventArgs args)
-        {
-            Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.glade b/src/Ryujinx/Ui/Windows/ControllerWindow.glade
deleted file mode 100644
index e433f5cc..00000000
--- a/src/Ryujinx/Ui/Windows/ControllerWindow.glade
+++ /dev/null
@@ -1,2241 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkAdjustment" id="_altSlotNumber">
-    <property name="upper">4</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">4</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerStrongRumble">
-    <property name="lower">0.1</property>
-    <property name="upper">10</property>
-    <property name="value">1.0</property>
-    <property name="step_increment">0.1</property>
-    <property name="page_increment">1.0</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerWeakRumble">
-    <property name="lower">0.1</property>
-    <property name="upper">10</property>
-    <property name="value">1.0</property>
-    <property name="step_increment">0.1</property>
-    <property name="page_increment">1.0</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerDeadzoneLeft">
-    <property name="upper">1</property>
-    <property name="value">0.050000000000000003</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerDeadzoneRight">
-    <property name="upper">1</property>
-    <property name="value">0.050000000000000003</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerRangeLeft">
-    <property name="upper">2</property>
-    <property name="value">1.000000000000000003</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerRangeRight">
-    <property name="upper">2</property>
-    <property name="value">1.000000000000000003</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_controllerTriggerThreshold">
-    <property name="upper">1</property>
-    <property name="value">0.5</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_gyroDeadzone">
-    <property name="upper">100</property>
-    <property name="value">0.01</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">0.10000000000000001</property>
-    <property name="page_size">0.10000000000000001</property>
-  </object>
-  <object class="GtkAdjustment" id="_sensitivity">
-    <property name="upper">1000</property>
-    <property name="value">100</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">4</property>
-  </object>
-  <object class="GtkAdjustment" id="_slotNumber">
-    <property name="upper">4</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">4</property>
-  </object>
-  <object class="GtkWindow" id="_controllerWin">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - Controller Settings</property>
-    <property name="modal">True</property>
-    <property name="window_position">center</property>
-    <property name="default_width">1200</property>
-    <property name="default_height">720</property>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
-    <child>
-      <object class="GtkBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkScrolledWindow">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="shadow_type">in</property>
-            <child>
-              <object class="GtkViewport">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkBox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkBox" id="HeadBox">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="margin_left">10</property>
-                        <property name="margin_top">10</property>
-                        <property name="margin_bottom">10</property>
-                        <child>
-                          <object class="GtkBox" id="DeviceBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_right">5</property>
-                                <property name="label" translatable="yes">Input Device</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkComboBoxText" id="_inputDevice">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="active">0</property>
-                                <property name="active_id">disabled</property>
-                                <items>
-                                  <item id="disabled" translatable="yes">Disabled</item>
-                                </items>
-                                <signal name="changed" handler="InputDevice_Changed" swapped="no"/>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="ControllerTypeBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_left">20</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">The controller's type</property>
-                                <property name="halign">center</property>
-                                <property name="margin_right">5</property>
-                                <property name="label" translatable="yes">Controller Type:</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkComboBoxText" id="_controllerType">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">The controller's type</property>
-                                <property name="active">0</property>
-                                <signal name="changed" handler="Controller_Changed" swapped="no"/>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="ProfileBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_left">20</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_right">5</property>
-                                <property name="label" translatable="yes">Profile:</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkComboBoxText" id="_profile">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_right">5</property>
-                                <property name="active">0</property>
-                                <property name="active_id">default</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkToggleButton">
-                                <property name="label" translatable="yes">Load</property>
-                                <property name="width_request">60</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="margin_right">5</property>
-                                <signal name="toggled" handler="ProfileLoad_Activated" swapped="no"/>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkToggleButton">
-                                <property name="label" translatable="yes">Add</property>
-                                <property name="width_request">60</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="margin_right">5</property>
-                                <signal name="toggled" handler="ProfileAdd_Activated" swapped="no"/>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkToggleButton">
-                                <property name="label" translatable="yes">Remove</property>
-                                <property name="width_request">60</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <signal name="toggled" handler="ProfileRemove_Activated" swapped="no"/>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">4</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="_settingsBox">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_left">10</property>
-                                <property name="margin_top">5</property>
-                                <child>
-                                  <object class="GtkBox" id="ButtonsBox">
-                                    <property name="width_request">156</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Buttons</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">A</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">B</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">X</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Y</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_a">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_b">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_x">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_y">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">+</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">4</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">-</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">5</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_minus">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">5</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_plus">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">4</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSeparator">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="LeftStickBox">
-                                    <property name="width_request">160</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_left">10</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Left Stick</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick Button</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStickButton">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_leftStickKeyboard">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStickDown">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStickUp">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStickLeft">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStickRight">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick Down</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick Up</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick Right</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick Left</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_leftStickController">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">LStick</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lStick">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_invertLStickX">
-                                            <property name="label" translatable="yes">Invert Stick X</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_invertLStickY">
-                                            <property name="label" translatable="yes">Invert Stick Y</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_rotateL90CW">
-                                            <property name="label" translatable="yes">Rotate 90° Clockwise</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_deadZoneLeftBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Deadzone Left</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkScale">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="adjustment">_controllerDeadzoneLeft</property>
-                                            <property name="round_digits">2</property>
-                                            <property name="digits">2</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">True</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_rangeLeftBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Range Left</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkScale">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="adjustment">_controllerRangeLeft</property>
-                                            <property name="round_digits">2</property>
-                                            <property name="digits">2</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">True</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">5</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSeparator">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="TriggerBox">
-                                    <property name="width_request">150</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_left">10</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Triggers</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">L</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">R</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_l">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_r">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">ZL</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">ZR</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_zL">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_zR">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_leftSideTriggerBox">
-                                        <property name="name">_sideTriggerBox</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Left SL</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Left SR</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lSl">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_lSr">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_rightSideTriggerBox">
-                                        <property name="name">_sideTriggerBox</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Right SL</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Right SR</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rSl">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rSr">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_triggerThresholdBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">start</property>
-                                            <property name="margin_left">10</property>
-                                            <property name="label" translatable="yes">Trigger Threshold</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkScale">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="adjustment">_controllerTriggerThreshold</property>
-                                            <property name="round_digits">2</property>
-                                            <property name="digits">2</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">True</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_left">10</property>
-                                <child>
-                                  <object class="GtkBox" id="DPadBox">
-                                    <property name="width_request">156</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="margin_top">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Directional Pad</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Dpad Up</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Dpad Down</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Dpad Left</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Dpad Right</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_dpadUp">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_dpadDown">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_dpadLeft">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_dpadRight">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">70</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_rumbleBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="margin_top">10</property>
-                                            <property name="margin_bottom">5</property>
-                                            <property name="label" translatable="yes">Rumble</property>
-                                            <attributes>
-                                              <attribute name="weight" value="bold"/>
-                                            </attributes>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_enableRumble">
-                                            <property name="label" translatable="yes">Enable</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkBox" id="_StrongMultiBox">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="margin_top">10</property>
-                                            <property name="orientation">vertical</property>
-                                            <child>
-                                              <object class="GtkLabel">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">False</property>
-                                                <property name="halign">start</property>
-                                                <property name="label" translatable="yes">Strong rumble multiplier</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="fill">True</property>
-                                                <property name="position">0</property>
-                                              </packing>
-                                            </child>
-                                            <child>
-                                              <object class="GtkScale">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="adjustment">_controllerStrongRumble</property>
-                                                <property name="round_digits">1</property>
-                                                <property name="digits">1</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">True</property>
-                                                <property name="fill">True</property>
-                                                <property name="position">1</property>
-                                              </packing>
-                                            </child>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkBox" id="_WeakMultiBox">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="margin_top">10</property>
-                                            <property name="orientation">vertical</property>
-                                            <child>
-                                              <object class="GtkLabel">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">False</property>
-                                                <property name="halign">start</property>
-                                                <property name="label" translatable="yes">Weak rumble multiplier</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="fill">True</property>
-                                                <property name="position">0</property>
-                                              </packing>
-                                            </child>
-                                            <child>
-                                              <object class="GtkScale">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="adjustment">_controllerWeakRumble</property>
-                                                <property name="round_digits">1</property>
-                                                <property name="digits">1</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">True</property>
-                                                <property name="fill">True</property>
-                                                <property name="position">1</property>
-                                              </packing>
-                                            </child>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">3</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSeparator">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="RightStickBox">
-                                    <property name="width_request">160</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_left">10</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Right Stick</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick Button</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStickButton">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_rightStickKeyboard">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick Up</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick Down</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick Left</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick Right</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStickUp">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStickDown">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStickLeft">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStickRight">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">3</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkGrid" id="_rightStickController">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="row_spacing">3</property>
-                                        <property name="column_spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="width_request">80</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">RStick</property>
-                                            <property name="xalign">0</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkToggleButton" id="_rStick">
-                                            <property name="label" translatable="yes"> </property>
-                                            <property name="width_request">65</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_invertRStickX">
-                                            <property name="label" translatable="yes">Invert Stick X</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_invertRStickY">
-                                            <property name="label" translatable="yes">Invert Stick Y</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_rotateR90CW">
-                                            <property name="label" translatable="yes">Rotate 90° Clockwise</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">2</property>
-                                            <property name="top_attach">2</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_deadZoneRightBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Deadzone Right</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkScale">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="adjustment">_controllerDeadzoneRight</property>
-                                            <property name="round_digits">2</property>
-                                            <property name="digits">2</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">True</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_rangeRightBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">10</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Range Right</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkScale">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="adjustment">_controllerRangeRight</property>
-                                            <property name="round_digits">2</property>
-                                            <property name="digits">2</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">True</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">5</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSeparator">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="_motionBox">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="margin_left">10</property>
-                                    <property name="margin_right">10</property>
-                                    <property name="orientation">vertical</property>
-                                    <property name="spacing">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">5</property>
-                                        <property name="label" translatable="yes">Motion</property>
-                                        <attributes>
-                                          <attribute name="weight" value="bold"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkCheckButton" id="_enableMotion">
-                                        <property name="label" translatable="yes">Enable Motion Controls</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="draw_indicator">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkCheckButton" id="_enableCemuHook">
-                                        <property name="label" translatable="yes">Use CemuHook compatible motion</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="draw_indicator">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_motionControllerSlot">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="margin_right">17</property>
-                                            <property name="label" translatable="yes">Controller Slot</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="padding">5</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkSpinButton" id="_slot">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="margin_left">10</property>
-                                            <property name="adjustment">_slotNumber</property>
-                                            <property name="climb_rate">1</property>
-                                            <property name="snap_to_ticks">True</property>
-                                            <property name="numeric">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="spacing">10</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="margin_right">5</property>
-                                            <property name="label" translatable="yes">Gyro Sensitivity %</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="padding">5</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkSpinButton">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="text" translatable="yes">0</property>
-                                            <property name="adjustment">_sensitivity</property>
-                                            <property name="climb_rate">1</property>
-                                            <property name="snap_to_ticks">True</property>
-                                            <property name="numeric">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_motionAltBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="orientation">vertical</property>
-                                        <child>
-                                          <object class="GtkCheckButton" id="_mirrorInput">
-                                            <property name="label" translatable="yes">Mirror Input</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="draw_indicator">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkBox">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="spacing">10</property>
-                                            <child>
-                                              <object class="GtkLabel">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">False</property>
-                                                <property name="label" translatable="yes">Right JoyCon Slot</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="fill">True</property>
-                                                <property name="padding">5</property>
-                                                <property name="position">0</property>
-                                              </packing>
-                                            </child>
-                                            <child>
-                                              <object class="GtkSpinButton" id="_slotRight">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="text" translatable="yes">0</property>
-                                                <property name="adjustment">_altSlotNumber</property>
-                                                <property name="climb_rate">1</property>
-                                                <property name="snap_to_ticks">True</property>
-                                                <property name="numeric">True</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="fill">True</property>
-                                                <property name="position">1</property>
-                                              </packing>
-                                            </child>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="padding">5</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">5</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_dsuServerHostBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="spacing">30</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Server Host</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="padding">5</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkEntry" id="_dsuServerHost">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">6</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkBox" id="_dsuServerPortBox">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="spacing">30</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="label" translatable="yes">Server Port</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="padding">5</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkEntry" id="_dsuServerPort">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">True</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">7</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="halign">start</property>
-                                        <property name="label" translatable="yes">Gyro Deadzone</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">8</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkScale">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="adjustment">_gyroDeadzone</property>
-                                        <property name="round_digits">2</property>
-                                        <property name="digits">2</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">9</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkImage" id="_controllerImage">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_left">10</property>
-                            <property name="margin_right">20</property>
-                            <property name="margin_top">5</property>
-                            <property name="margin_bottom">5</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButtonBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_right">5</property>
-            <property name="margin_top">3</property>
-            <property name="margin_bottom">3</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkToggleButton" id="SaveToggle">
-                <property name="label" translatable="yes">Save</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToggleButton" id="CloseToggle">
-                <property name="label" translatable="yes">Close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="margin_left">4</property>
-                <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="padding">5</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Windows/DlcWindow.cs b/src/Ryujinx/Ui/Windows/DlcWindow.cs
deleted file mode 100644
index 9f717946..00000000
--- a/src/Ryujinx/Ui/Windows/DlcWindow.cs
+++ /dev/null
@@ -1,280 +0,0 @@
-using Gtk;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Utilities;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using GUI = Gtk.Builder.ObjectAttribute;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class DlcWindow : Window
-    {
-        private readonly VirtualFileSystem _virtualFileSystem;
-        private readonly string _titleId;
-        private readonly string _dlcJsonPath;
-        private readonly List<DownloadableContentContainer> _dlcContainerList;
-
-        private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] Label _baseTitleInfoLabel;
-        [GUI] TreeView _dlcTreeView;
-        [GUI] TreeSelection _dlcTreeSelection;
-#pragma warning restore CS0649, IDE0044
-
-        public DlcWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.DlcWindow.glade"), virtualFileSystem, titleId, titleName) { }
-
-        private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_dlcWindow"))
-        {
-            builder.Autoconnect(this);
-
-            _titleId = titleId;
-            _virtualFileSystem = virtualFileSystem;
-            _dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json");
-            _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";
-
-            try
-            {
-                _dlcContainerList = JsonHelper.DeserializeFromFile(_dlcJsonPath, _serializerContext.ListDownloadableContentContainer);
-            }
-            catch
-            {
-                _dlcContainerList = new List<DownloadableContentContainer>();
-            }
-
-            _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string));
-
-            CellRendererToggle enableToggle = new();
-            enableToggle.Toggled += (sender, args) =>
-            {
-                _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
-                bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0);
-                _dlcTreeView.Model.SetValue(treeIter, 0, newValue);
-
-                if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
-                {
-                    do
-                    {
-                        _dlcTreeView.Model.SetValue(childIter, 0, newValue);
-                    }
-                    while (_dlcTreeView.Model.IterNext(ref childIter));
-                }
-            };
-
-            _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
-            _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1);
-            _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);
-
-            foreach (DownloadableContentContainer dlcContainer in _dlcContainerList)
-            {
-                if (File.Exists(dlcContainer.ContainerPath))
-                {
-                    // The parent tree item has its own "enabled" check box, but it's the actual
-                    // nca entries that store the enabled / disabled state. A bit of a UI inconsistency.
-                    // Maybe a tri-state check box would be better, but for now we check the parent
-                    // "enabled" box if all child NCAs are enabled. Usually fine since each nsp has only one nca.
-                    bool areAllContentPacksEnabled = dlcContainer.DownloadableContentNcaList.TrueForAll((nca) => nca.Enabled);
-                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(areAllContentPacksEnabled, "", dlcContainer.ContainerPath);
-
-                    using FileStream containerFile = File.OpenRead(dlcContainer.ContainerPath);
-
-                    PartitionFileSystem pfs = new();
-                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
-
-                    _virtualFileSystem.ImportTickets(pfs);
-
-                    foreach (DownloadableContentNca dlcNca in dlcContainer.DownloadableContentNcaList)
-                    {
-                        using var ncaFile = new UniqueRef<IFile>();
-
-                        pfs.OpenFile(ref ncaFile.Ref, dlcNca.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-                        Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), dlcContainer.ContainerPath);
-
-                        if (nca != null)
-                        {
-                            ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.FullPath);
-                        }
-                    }
-                }
-                else
-                {
-                    // DLC file moved or renamed. Allow the user to remove it without crashing the whole dialog.
-                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", $"(MISSING) {dlcContainer.ContainerPath}");
-                }
-            }
-        }
-
-        private Nca TryCreateNca(IStorage ncaStorage, string containerPath)
-        {
-            try
-            {
-                return new Nca(_virtualFileSystem.KeySet, ncaStorage);
-            }
-            catch (Exception exception)
-            {
-                GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {containerPath}");
-            }
-
-            return null;
-        }
-
-        private void AddButton_Clicked(object sender, EventArgs args)
-        {
-            FileChooserNative fileChooser = new("Select DLC files", this, FileChooserAction.Open, "Add", "Cancel")
-            {
-                SelectMultiple = true,
-            };
-
-            FileFilter filter = new()
-            {
-                Name = "Switch Game DLCs",
-            };
-            filter.AddPattern("*.nsp");
-
-            fileChooser.AddFilter(filter);
-
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                foreach (string containerPath in fileChooser.Filenames)
-                {
-                    if (!File.Exists(containerPath))
-                    {
-                        return;
-                    }
-
-                    using FileStream containerFile = File.OpenRead(containerPath);
-
-                    PartitionFileSystem pfs = new();
-                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
-                    bool containsDlc = false;
-
-                    _virtualFileSystem.ImportTickets(pfs);
-
-                    TreeIter? parentIter = null;
-
-                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
-                    {
-                        using var ncaFile = new UniqueRef<IFile>();
-
-                        pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
-                        Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), containerPath);
-
-                        if (nca == null)
-                        {
-                            continue;
-                        }
-
-                        if (nca.Header.ContentType == NcaContentType.PublicData)
-                        {
-                            if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000).ToString("x16") != _titleId)
-                            {
-                                break;
-                            }
-
-                            parentIter ??= ((TreeStore)_dlcTreeView.Model).AppendValues(true, "", containerPath);
-
-                            ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter.Value, true, nca.Header.TitleId.ToString("X16"), fileEntry.FullPath);
-                            containsDlc = true;
-                        }
-                    }
-
-                    if (!containsDlc)
-                    {
-                        GtkDialog.CreateErrorDialog("The specified file does not contain DLC for the selected title!");
-                    }
-                }
-            }
-
-            fileChooser.Dispose();
-        }
-
-        private void RemoveButton_Clicked(object sender, EventArgs args)
-        {
-            if (_dlcTreeSelection.GetSelected(out ITreeModel treeModel, out TreeIter treeIter))
-            {
-                if (_dlcTreeView.Model.IterParent(out TreeIter parentIter, treeIter) && _dlcTreeView.Model.IterNChildren(parentIter) <= 1)
-                {
-                    ((TreeStore)treeModel).Remove(ref parentIter);
-                }
-                else
-                {
-                    ((TreeStore)treeModel).Remove(ref treeIter);
-                }
-            }
-        }
-
-        private void RemoveAllButton_Clicked(object sender, EventArgs args)
-        {
-            List<TreeIter> toRemove = new();
-
-            if (_dlcTreeView.Model.GetIterFirst(out TreeIter iter))
-            {
-                do
-                {
-                    toRemove.Add(iter);
-                }
-                while (_dlcTreeView.Model.IterNext(ref iter));
-            }
-
-            foreach (TreeIter i in toRemove)
-            {
-                TreeIter j = i;
-                ((TreeStore)_dlcTreeView.Model).Remove(ref j);
-            }
-        }
-
-        private void SaveButton_Clicked(object sender, EventArgs args)
-        {
-            _dlcContainerList.Clear();
-
-            if (_dlcTreeView.Model.GetIterFirst(out TreeIter parentIter))
-            {
-                do
-                {
-                    if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, parentIter))
-                    {
-                        DownloadableContentContainer dlcContainer = new()
-                        {
-                            ContainerPath = (string)_dlcTreeView.Model.GetValue(parentIter, 2),
-                            DownloadableContentNcaList = new List<DownloadableContentNca>(),
-                        };
-
-                        do
-                        {
-                            dlcContainer.DownloadableContentNcaList.Add(new DownloadableContentNca
-                            {
-                                Enabled = (bool)_dlcTreeView.Model.GetValue(childIter, 0),
-                                TitleId = Convert.ToUInt64(_dlcTreeView.Model.GetValue(childIter, 1).ToString(), 16),
-                                FullPath = (string)_dlcTreeView.Model.GetValue(childIter, 2),
-                            });
-                        }
-                        while (_dlcTreeView.Model.IterNext(ref childIter));
-
-                        _dlcContainerList.Add(dlcContainer);
-                    }
-                }
-                while (_dlcTreeView.Model.IterNext(ref parentIter));
-            }
-
-            JsonHelper.SerializeToFile(_dlcJsonPath, _dlcContainerList, _serializerContext.ListDownloadableContentContainer);
-
-            Dispose();
-        }
-
-        private void CancelButton_Clicked(object sender, EventArgs args)
-        {
-            Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/DlcWindow.glade b/src/Ryujinx/Ui/Windows/DlcWindow.glade
deleted file mode 100644
index bdb0e647..00000000
--- a/src/Ryujinx/Ui/Windows/DlcWindow.glade
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.36.0 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkWindow" id="_dlcWindow">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - DLC Manager</property>
-    <property name="modal">True</property>
-    <property name="window_position">center</property>
-    <property name="default_width">550</property>
-    <property name="default_height">350</property>
-    <child>
-      <object class="GtkBox" id="MainBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkBox" id="DlcBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkLabel" id="_baseTitleInfoLabel">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="label" translatable="yes">Available DLC</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkViewport">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkTreeView" id="_dlcTreeView">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="headers_clickable">False</property>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection" id="_dlcTreeSelection"/>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkButtonBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="layout_style">start</property>
-                <child>
-                  <object class="GtkButton" id="_addUpdate">
-                    <property name="label" translatable="yes">Add</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Adds a DLC to this list</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="AddButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_removeUpdate">
-                    <property name="label" translatable="yes">Remove</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Removes the selected DLC</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="RemoveButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_removeAllButton">
-                    <property name="label" translatable="yes">Remove All</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Removes all DLCs</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="RemoveAllButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButtonBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="layout_style">end</property>
-                <child>
-                  <object class="GtkButton" id="_saveButton">
-                    <property name="label" translatable="yes">Save</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_cancelButton">
-                    <property name="label" translatable="yes">Cancel</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Windows/SettingsWindow.cs b/src/Ryujinx/Ui/Windows/SettingsWindow.cs
deleted file mode 100644
index dabef14d..00000000
--- a/src/Ryujinx/Ui/Windows/SettingsWindow.cs
+++ /dev/null
@@ -1,847 +0,0 @@
-using Gtk;
-using LibHac.Tools.FsSystem;
-using Ryujinx.Audio.Backends.OpenAL;
-using Ryujinx.Audio.Backends.SDL2;
-using Ryujinx.Audio.Backends.SoundIo;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Multiplayer;
-using Ryujinx.Common.GraphicsDriver;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS.Services.Time.TimeZone;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration.System;
-using Ryujinx.Ui.Helper;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Net.NetworkInformation;
-using System.Reflection;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using GUI = Gtk.Builder.ObjectAttribute;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class SettingsWindow : Window
-    {
-        private readonly MainWindow _parent;
-        private readonly ListStore _gameDirsBoxStore;
-        private readonly ListStore _audioBackendStore;
-        private readonly TimeZoneContentManager _timeZoneContentManager;
-        private readonly HashSet<string> _validTzRegions;
-
-        private long _systemTimeOffset;
-        private float _previousVolumeLevel;
-        private bool _directoryChanged = false;
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] CheckButton _traceLogToggle;
-        [GUI] CheckButton _errorLogToggle;
-        [GUI] CheckButton _warningLogToggle;
-        [GUI] CheckButton _infoLogToggle;
-        [GUI] CheckButton _stubLogToggle;
-        [GUI] CheckButton _debugLogToggle;
-        [GUI] CheckButton _fileLogToggle;
-        [GUI] CheckButton _guestLogToggle;
-        [GUI] CheckButton _fsAccessLogToggle;
-        [GUI] Adjustment _fsLogSpinAdjustment;
-        [GUI] ComboBoxText _graphicsDebugLevel;
-        [GUI] CheckButton _dockedModeToggle;
-        [GUI] CheckButton _discordToggle;
-        [GUI] CheckButton _checkUpdatesToggle;
-        [GUI] CheckButton _showConfirmExitToggle;
-        [GUI] RadioButton _hideCursorNever;
-        [GUI] RadioButton _hideCursorOnIdle;
-        [GUI] RadioButton _hideCursorAlways;
-        [GUI] CheckButton _vSyncToggle;
-        [GUI] CheckButton _shaderCacheToggle;
-        [GUI] CheckButton _textureRecompressionToggle;
-        [GUI] CheckButton _macroHLEToggle;
-        [GUI] CheckButton _ptcToggle;
-        [GUI] CheckButton _internetToggle;
-        [GUI] CheckButton _fsicToggle;
-        [GUI] RadioButton _mmSoftware;
-        [GUI] RadioButton _mmHost;
-        [GUI] RadioButton _mmHostUnsafe;
-        [GUI] CheckButton _expandRamToggle;
-        [GUI] CheckButton _ignoreToggle;
-        [GUI] CheckButton _directKeyboardAccess;
-        [GUI] CheckButton _directMouseAccess;
-        [GUI] ComboBoxText _systemLanguageSelect;
-        [GUI] ComboBoxText _systemRegionSelect;
-        [GUI] Entry _systemTimeZoneEntry;
-        [GUI] EntryCompletion _systemTimeZoneCompletion;
-        [GUI] Box _audioBackendBox;
-        [GUI] ComboBox _audioBackendSelect;
-        [GUI] Label _audioVolumeLabel;
-        [GUI] Scale _audioVolumeSlider;
-        [GUI] SpinButton _systemTimeYearSpin;
-        [GUI] SpinButton _systemTimeMonthSpin;
-        [GUI] SpinButton _systemTimeDaySpin;
-        [GUI] SpinButton _systemTimeHourSpin;
-        [GUI] SpinButton _systemTimeMinuteSpin;
-        [GUI] Adjustment _systemTimeYearSpinAdjustment;
-        [GUI] Adjustment _systemTimeMonthSpinAdjustment;
-        [GUI] Adjustment _systemTimeDaySpinAdjustment;
-        [GUI] Adjustment _systemTimeHourSpinAdjustment;
-        [GUI] Adjustment _systemTimeMinuteSpinAdjustment;
-        [GUI] ComboBoxText _multiLanSelect;
-        [GUI] ComboBoxText _multiModeSelect;
-        [GUI] CheckButton _custThemeToggle;
-        [GUI] Entry _custThemePath;
-        [GUI] ToggleButton _browseThemePath;
-        [GUI] Label _custThemePathLabel;
-        [GUI] TreeView _gameDirsBox;
-        [GUI] Entry _addGameDirBox;
-        [GUI] ComboBoxText _galThreading;
-        [GUI] Entry _graphicsShadersDumpPath;
-        [GUI] ComboBoxText _anisotropy;
-        [GUI] ComboBoxText _aspectRatio;
-        [GUI] ComboBoxText _antiAliasing;
-        [GUI] ComboBoxText _scalingFilter;
-        [GUI] ComboBoxText _graphicsBackend;
-        [GUI] ComboBoxText _preferredGpu;
-        [GUI] ComboBoxText _resScaleCombo;
-        [GUI] Entry _resScaleText;
-        [GUI] Adjustment _scalingFilterLevel;
-        [GUI] Scale _scalingFilterSlider;
-        [GUI] ToggleButton _configureController1;
-        [GUI] ToggleButton _configureController2;
-        [GUI] ToggleButton _configureController3;
-        [GUI] ToggleButton _configureController4;
-        [GUI] ToggleButton _configureController5;
-        [GUI] ToggleButton _configureController6;
-        [GUI] ToggleButton _configureController7;
-        [GUI] ToggleButton _configureController8;
-        [GUI] ToggleButton _configureControllerH;
-
-#pragma warning restore CS0649, IDE0044
-
-        public SettingsWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(parent, new Builder("Ryujinx.Ui.Windows.SettingsWindow.glade"), virtualFileSystem, contentManager) { }
-
-        private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : base(builder.GetRawOwnedObject("_settingsWin"))
-        {
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            _parent = parent;
-
-            builder.Autoconnect(this);
-
-            _timeZoneContentManager = new TimeZoneContentManager();
-            _timeZoneContentManager.InitializeInstance(virtualFileSystem, contentManager, IntegrityCheckLevel.None);
-
-            _validTzRegions = new HashSet<string>(_timeZoneContentManager.LocationNameCache.Length, StringComparer.Ordinal); // Zone regions are identifiers. Must match exactly.
-
-            // Bind Events.
-            _configureController1.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player1);
-            _configureController2.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player2);
-            _configureController3.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player3);
-            _configureController4.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player4);
-            _configureController5.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player5);
-            _configureController6.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player6);
-            _configureController7.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player7);
-            _configureController8.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Player8);
-            _configureControllerH.Pressed += (sender, args) => ConfigureController_Pressed(sender, PlayerIndex.Handheld);
-            _systemTimeZoneEntry.FocusOutEvent += TimeZoneEntry_FocusOut;
-
-            _resScaleCombo.Changed += (sender, args) => _resScaleText.Visible = _resScaleCombo.ActiveId == "-1";
-            _scalingFilter.Changed += (sender, args) => _scalingFilterSlider.Visible = _scalingFilter.ActiveId == "2";
-            _galThreading.Changed += (sender, args) =>
-            {
-                if (_galThreading.ActiveId != ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString())
-                {
-                    GtkDialog.CreateInfoDialog("Warning - Backend Threading", "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.");
-                }
-            };
-
-            // Setup Currents.
-            if (ConfigurationState.Instance.Logger.EnableTrace)
-            {
-                _traceLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableFileLog)
-            {
-                _fileLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableError)
-            {
-                _errorLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableWarn)
-            {
-                _warningLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableInfo)
-            {
-                _infoLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableStub)
-            {
-                _stubLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableDebug)
-            {
-                _debugLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableGuest)
-            {
-                _guestLogToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Logger.EnableFsAccessLog)
-            {
-                _fsAccessLogToggle.Click();
-            }
-
-            foreach (GraphicsDebugLevel level in Enum.GetValues<GraphicsDebugLevel>())
-            {
-                _graphicsDebugLevel.Append(level.ToString(), level.ToString());
-            }
-
-            _graphicsDebugLevel.SetActiveId(ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value.ToString());
-
-            if (ConfigurationState.Instance.System.EnableDockedMode)
-            {
-                _dockedModeToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.EnableDiscordIntegration)
-            {
-                _discordToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.CheckUpdatesOnStart)
-            {
-                _checkUpdatesToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.ShowConfirmExit)
-            {
-                _showConfirmExitToggle.Click();
-            }
-
-            switch (ConfigurationState.Instance.HideCursor.Value)
-            {
-                case HideCursorMode.Never:
-                    _hideCursorNever.Click();
-                    break;
-                case HideCursorMode.OnIdle:
-                    _hideCursorOnIdle.Click();
-                    break;
-                case HideCursorMode.Always:
-                    _hideCursorAlways.Click();
-                    break;
-            }
-
-            if (ConfigurationState.Instance.Graphics.EnableVsync)
-            {
-                _vSyncToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Graphics.EnableShaderCache)
-            {
-                _shaderCacheToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Graphics.EnableTextureRecompression)
-            {
-                _textureRecompressionToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Graphics.EnableMacroHLE)
-            {
-                _macroHLEToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.System.EnablePtc)
-            {
-                _ptcToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.System.EnableInternetAccess)
-            {
-                _internetToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.System.EnableFsIntegrityChecks)
-            {
-                _fsicToggle.Click();
-            }
-
-            switch (ConfigurationState.Instance.System.MemoryManagerMode.Value)
-            {
-                case MemoryManagerMode.SoftwarePageTable:
-                    _mmSoftware.Click();
-                    break;
-                case MemoryManagerMode.HostMapped:
-                    _mmHost.Click();
-                    break;
-                case MemoryManagerMode.HostMappedUnsafe:
-                    _mmHostUnsafe.Click();
-                    break;
-            }
-
-            if (ConfigurationState.Instance.System.ExpandRam)
-            {
-                _expandRamToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.System.IgnoreMissingServices)
-            {
-                _ignoreToggle.Click();
-            }
-
-            if (ConfigurationState.Instance.Hid.EnableKeyboard)
-            {
-                _directKeyboardAccess.Click();
-            }
-
-            if (ConfigurationState.Instance.Hid.EnableMouse)
-            {
-                _directMouseAccess.Click();
-            }
-
-            if (ConfigurationState.Instance.Ui.EnableCustomTheme)
-            {
-                _custThemeToggle.Click();
-            }
-
-            // Custom EntryCompletion Columns. If added to glade, need to override more signals
-            ListStore tzList = new(typeof(string), typeof(string), typeof(string));
-            _systemTimeZoneCompletion.Model = tzList;
-
-            CellRendererText offsetCol = new();
-            CellRendererText abbrevCol = new();
-
-            _systemTimeZoneCompletion.PackStart(offsetCol, false);
-            _systemTimeZoneCompletion.AddAttribute(offsetCol, "text", 0);
-            _systemTimeZoneCompletion.TextColumn = 1; // Regions Column
-            _systemTimeZoneCompletion.PackStart(abbrevCol, false);
-            _systemTimeZoneCompletion.AddAttribute(abbrevCol, "text", 2);
-
-            int maxLocationLength = 0;
-
-            foreach (var (offset, location, abbr) in _timeZoneContentManager.ParseTzOffsets())
-            {
-                var hours = Math.DivRem(offset, 3600, out int seconds);
-                var minutes = Math.Abs(seconds) / 60;
-
-                var abbr2 = (abbr.StartsWith('+') || abbr.StartsWith('-')) ? string.Empty : abbr;
-
-                tzList.AppendValues($"UTC{hours:+0#;-0#;+00}:{minutes:D2} ", location, abbr2);
-                _validTzRegions.Add(location);
-
-                maxLocationLength = Math.Max(maxLocationLength, location.Length);
-            }
-
-            _systemTimeZoneEntry.WidthChars = Math.Max(20, maxLocationLength + 1); // Ensure minimum Entry width
-            _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
-
-            _systemTimeZoneCompletion.MatchFunc = TimeZoneMatchFunc;
-
-            _systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString());
-            _systemRegionSelect.SetActiveId(ConfigurationState.Instance.System.Region.Value.ToString());
-            _galThreading.SetActiveId(ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString());
-            _resScaleCombo.SetActiveId(ConfigurationState.Instance.Graphics.ResScale.Value.ToString());
-            _anisotropy.SetActiveId(ConfigurationState.Instance.Graphics.MaxAnisotropy.Value.ToString());
-            _aspectRatio.SetActiveId(((int)ConfigurationState.Instance.Graphics.AspectRatio.Value).ToString());
-            _graphicsBackend.SetActiveId(((int)ConfigurationState.Instance.Graphics.GraphicsBackend.Value).ToString());
-            _antiAliasing.SetActiveId(((int)ConfigurationState.Instance.Graphics.AntiAliasing.Value).ToString());
-            _scalingFilter.SetActiveId(((int)ConfigurationState.Instance.Graphics.ScalingFilter.Value).ToString());
-
-            UpdatePreferredGpuComboBox();
-
-            _graphicsBackend.Changed += (sender, e) => UpdatePreferredGpuComboBox();
-            PopulateNetworkInterfaces();
-            _multiLanSelect.SetActiveId(ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value);
-            _multiModeSelect.SetActiveId(ConfigurationState.Instance.Multiplayer.Mode.Value.ToString());
-
-            _custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath;
-            _resScaleText.Buffer.Text = ConfigurationState.Instance.Graphics.ResScaleCustom.Value.ToString();
-            _scalingFilterLevel.Value = ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value;
-            _resScaleText.Visible = _resScaleCombo.ActiveId == "-1";
-            _scalingFilterSlider.Visible = _scalingFilter.ActiveId == "2";
-            _graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath;
-            _fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode;
-            _systemTimeOffset = ConfigurationState.Instance.System.SystemTimeOffset;
-
-            _gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0);
-            _gameDirsBoxStore = new ListStore(typeof(string));
-            _gameDirsBox.Model = _gameDirsBoxStore;
-
-            foreach (string gameDir in ConfigurationState.Instance.Ui.GameDirs.Value)
-            {
-                _gameDirsBoxStore.AppendValues(gameDir);
-            }
-
-            if (_custThemeToggle.Active == false)
-            {
-                _custThemePath.Sensitive = false;
-                _custThemePathLabel.Sensitive = false;
-                _browseThemePath.Sensitive = false;
-            }
-
-            // Setup system time spinners
-            UpdateSystemTimeSpinners();
-
-            _audioBackendStore = new ListStore(typeof(string), typeof(AudioBackend));
-
-            TreeIter openAlIter = _audioBackendStore.AppendValues("OpenAL", AudioBackend.OpenAl);
-            TreeIter soundIoIter = _audioBackendStore.AppendValues("SoundIO", AudioBackend.SoundIo);
-            TreeIter sdl2Iter = _audioBackendStore.AppendValues("SDL2", AudioBackend.SDL2);
-            TreeIter dummyIter = _audioBackendStore.AppendValues("Dummy", AudioBackend.Dummy);
-
-            _audioBackendSelect = ComboBox.NewWithModelAndEntry(_audioBackendStore);
-            _audioBackendSelect.EntryTextColumn = 0;
-            _audioBackendSelect.Entry.IsEditable = false;
-
-            switch (ConfigurationState.Instance.System.AudioBackend.Value)
-            {
-                case AudioBackend.OpenAl:
-                    _audioBackendSelect.SetActiveIter(openAlIter);
-                    break;
-                case AudioBackend.SoundIo:
-                    _audioBackendSelect.SetActiveIter(soundIoIter);
-                    break;
-                case AudioBackend.SDL2:
-                    _audioBackendSelect.SetActiveIter(sdl2Iter);
-                    break;
-                case AudioBackend.Dummy:
-                    _audioBackendSelect.SetActiveIter(dummyIter);
-                    break;
-                default:
-                    throw new InvalidOperationException($"{nameof(ConfigurationState.Instance.System.AudioBackend)} contains an invalid value: {ConfigurationState.Instance.System.AudioBackend.Value}");
-            }
-
-            _audioBackendBox.Add(_audioBackendSelect);
-            _audioBackendSelect.Show();
-
-            _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume;
-            _audioVolumeLabel = new Label("Volume: ");
-            _audioVolumeSlider = new Scale(Orientation.Horizontal, 0, 100, 1);
-            _audioVolumeLabel.MarginStart = 10;
-            _audioVolumeSlider.ValuePos = PositionType.Right;
-            _audioVolumeSlider.WidthRequest = 200;
-
-            _audioVolumeSlider.Value = _previousVolumeLevel * 100;
-            _audioVolumeSlider.ValueChanged += VolumeSlider_OnChange;
-            _audioBackendBox.Add(_audioVolumeLabel);
-            _audioBackendBox.Add(_audioVolumeSlider);
-            _audioVolumeLabel.Show();
-            _audioVolumeSlider.Show();
-
-            bool openAlIsSupported = false;
-            bool soundIoIsSupported = false;
-            bool sdl2IsSupported = false;
-
-            Task.Run(() =>
-            {
-                openAlIsSupported = OpenALHardwareDeviceDriver.IsSupported;
-                soundIoIsSupported = !OperatingSystem.IsMacOS() && SoundIoHardwareDeviceDriver.IsSupported;
-                sdl2IsSupported = SDL2HardwareDeviceDriver.IsSupported;
-            });
-
-            // This function runs whenever the dropdown is opened
-            _audioBackendSelect.SetCellDataFunc(_audioBackendSelect.Cells[0], (layout, cell, model, iter) =>
-            {
-                cell.Sensitive = ((AudioBackend)_audioBackendStore.GetValue(iter, 1)) switch
-                {
-                    AudioBackend.OpenAl => openAlIsSupported,
-                    AudioBackend.SoundIo => soundIoIsSupported,
-                    AudioBackend.SDL2 => sdl2IsSupported,
-                    AudioBackend.Dummy => true,
-                    _ => throw new InvalidOperationException($"{nameof(_audioBackendStore)} contains an invalid value for iteration {iter}: {_audioBackendStore.GetValue(iter, 1)}"),
-                };
-            });
-
-            if (OperatingSystem.IsMacOS())
-            {
-                var store = (_graphicsBackend.Model as ListStore);
-                store.GetIter(out TreeIter openglIter, new TreePath(new[] { 1 }));
-                store.Remove(ref openglIter);
-
-                _graphicsBackend.Model = store;
-            }
-        }
-
-        private void UpdatePreferredGpuComboBox()
-        {
-            _preferredGpu.RemoveAll();
-
-            if (Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId) == GraphicsBackend.Vulkan)
-            {
-                var devices = Graphics.Vulkan.VulkanRenderer.GetPhysicalDevices();
-                string preferredGpuIdFromConfig = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
-                string preferredGpuId = preferredGpuIdFromConfig;
-                bool noGpuId = string.IsNullOrEmpty(preferredGpuIdFromConfig);
-
-                foreach (var device in devices)
-                {
-                    string dGpu = device.IsDiscrete ? " (dGPU)" : "";
-                    _preferredGpu.Append(device.Id, $"{device.Name}{dGpu}");
-
-                    // If there's no GPU selected yet, we just pick the first GPU.
-                    // If there's a discrete GPU available, we always prefer that over the previous selection,
-                    // as it is likely to have better performance and more features.
-                    // If the configuration file already has a GPU selection, we always prefer that instead.
-                    if (noGpuId && (string.IsNullOrEmpty(preferredGpuId) || device.IsDiscrete))
-                    {
-                        preferredGpuId = device.Id;
-                    }
-                }
-
-                if (!string.IsNullOrEmpty(preferredGpuId))
-                {
-                    _preferredGpu.SetActiveId(preferredGpuId);
-                }
-            }
-        }
-
-        private void PopulateNetworkInterfaces()
-        {
-            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
-
-            foreach (NetworkInterface nif in interfaces)
-            {
-                string guid = nif.Id;
-                string name = nif.Name;
-
-                _multiLanSelect.Append(guid, name);
-            }
-        }
-
-        private void UpdateSystemTimeSpinners()
-        {
-            //Bind system time events
-            _systemTimeYearSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
-            _systemTimeMonthSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
-            _systemTimeDaySpin.ValueChanged -= SystemTimeSpin_ValueChanged;
-            _systemTimeHourSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
-            _systemTimeMinuteSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
-
-            //Apply actual system time + SystemTimeOffset to system time spin buttons
-            DateTime systemTime = DateTime.Now.AddSeconds(_systemTimeOffset);
-
-            _systemTimeYearSpinAdjustment.Value = systemTime.Year;
-            _systemTimeMonthSpinAdjustment.Value = systemTime.Month;
-            _systemTimeDaySpinAdjustment.Value = systemTime.Day;
-            _systemTimeHourSpinAdjustment.Value = systemTime.Hour;
-            _systemTimeMinuteSpinAdjustment.Value = systemTime.Minute;
-
-            //Format spin buttons text to include leading zeros
-            _systemTimeYearSpin.Text = systemTime.Year.ToString("0000");
-            _systemTimeMonthSpin.Text = systemTime.Month.ToString("00");
-            _systemTimeDaySpin.Text = systemTime.Day.ToString("00");
-            _systemTimeHourSpin.Text = systemTime.Hour.ToString("00");
-            _systemTimeMinuteSpin.Text = systemTime.Minute.ToString("00");
-
-            //Bind system time events
-            _systemTimeYearSpin.ValueChanged += SystemTimeSpin_ValueChanged;
-            _systemTimeMonthSpin.ValueChanged += SystemTimeSpin_ValueChanged;
-            _systemTimeDaySpin.ValueChanged += SystemTimeSpin_ValueChanged;
-            _systemTimeHourSpin.ValueChanged += SystemTimeSpin_ValueChanged;
-            _systemTimeMinuteSpin.ValueChanged += SystemTimeSpin_ValueChanged;
-        }
-
-        private void SaveSettings()
-        {
-            if (_directoryChanged)
-            {
-                List<string> gameDirs = new();
-
-                _gameDirsBoxStore.GetIterFirst(out TreeIter treeIter);
-
-                for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++)
-                {
-                    gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0));
-
-                    _gameDirsBoxStore.IterNext(ref treeIter);
-                }
-
-                ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
-
-                _directoryChanged = false;
-            }
-
-            HideCursorMode hideCursor = HideCursorMode.Never;
-
-            if (_hideCursorOnIdle.Active)
-            {
-                hideCursor = HideCursorMode.OnIdle;
-            }
-
-            if (_hideCursorAlways.Active)
-            {
-                hideCursor = HideCursorMode.Always;
-            }
-
-            if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f)
-            {
-                resScaleCustom = 1.0f;
-            }
-
-            if (_validTzRegions.Contains(_systemTimeZoneEntry.Text))
-            {
-                ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneEntry.Text;
-            }
-
-            MemoryManagerMode memoryMode = MemoryManagerMode.SoftwarePageTable;
-
-            if (_mmHost.Active)
-            {
-                memoryMode = MemoryManagerMode.HostMapped;
-            }
-
-            if (_mmHostUnsafe.Active)
-            {
-                memoryMode = MemoryManagerMode.HostMappedUnsafe;
-            }
-
-            BackendThreading backendThreading = Enum.Parse<BackendThreading>(_galThreading.ActiveId);
-            if (ConfigurationState.Instance.Graphics.BackendThreading != backendThreading)
-            {
-                DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off);
-            }
-
-            ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active;
-            ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active;
-            ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId);
-            ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
-            ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
-            ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
-            ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active;
-            ConfigurationState.Instance.HideCursor.Value = hideCursor;
-            ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
-            ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
-            ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
-            ConfigurationState.Instance.Graphics.EnableMacroHLE.Value = _macroHLEToggle.Active;
-            ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
-            ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
-            ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
-            ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode;
-            ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active;
-            ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active;
-            ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active;
-            ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active;
-            ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active;
-            ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId);
-            ConfigurationState.Instance.System.Region.Value = Enum.Parse<Common.Configuration.System.Region>(_systemRegionSelect.ActiveId);
-            ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
-            ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text;
-            ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
-            ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
-            ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture);
-            ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
-            ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading;
-            ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId);
-            ConfigurationState.Instance.Graphics.PreferredGpu.Value = _preferredGpu.ActiveId;
-            ConfigurationState.Instance.Graphics.ResScale.Value = int.Parse(_resScaleCombo.ActiveId);
-            ConfigurationState.Instance.Graphics.ResScaleCustom.Value = resScaleCustom;
-            ConfigurationState.Instance.System.AudioVolume.Value = (float)_audioVolumeSlider.Value / 100.0f;
-            ConfigurationState.Instance.Graphics.AntiAliasing.Value = Enum.Parse<AntiAliasing>(_antiAliasing.ActiveId);
-            ConfigurationState.Instance.Graphics.ScalingFilter.Value = Enum.Parse<ScalingFilter>(_scalingFilter.ActiveId);
-            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value = (int)_scalingFilterLevel.Value;
-            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _multiLanSelect.ActiveId;
-
-            _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume.Value;
-
-            ConfigurationState.Instance.Multiplayer.Mode.Value = Enum.Parse<MultiplayerMode>(_multiModeSelect.ActiveId);
-            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _multiLanSelect.ActiveId;
-
-            if (_audioBackendSelect.GetActiveIter(out TreeIter activeIter))
-            {
-                ConfigurationState.Instance.System.AudioBackend.Value = (AudioBackend)_audioBackendStore.GetValue(activeIter, 1);
-            }
-
-            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-
-            _parent.UpdateInternetAccess();
-            MainWindow.UpdateGraphicsConfig();
-            ThemeHelper.ApplyTheme();
-        }
-
-        //
-        // Events
-        //
-        private void TimeZoneEntry_FocusOut(object sender, FocusOutEventArgs e)
-        {
-            if (!_validTzRegions.Contains(_systemTimeZoneEntry.Text))
-            {
-                _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
-            }
-        }
-
-        private bool TimeZoneMatchFunc(EntryCompletion compl, string key, TreeIter iter)
-        {
-            key = key.Trim().Replace(' ', '_');
-
-            return ((string)compl.Model.GetValue(iter, 1)).Contains(key, StringComparison.OrdinalIgnoreCase) || // region
-                   ((string)compl.Model.GetValue(iter, 2)).StartsWith(key, StringComparison.OrdinalIgnoreCase) || // abbr
-                   ((string)compl.Model.GetValue(iter, 0))[3..].StartsWith(key); // offset
-        }
-
-        private void SystemTimeSpin_ValueChanged(object sender, EventArgs e)
-        {
-            int year = _systemTimeYearSpin.ValueAsInt;
-            int month = _systemTimeMonthSpin.ValueAsInt;
-            int day = _systemTimeDaySpin.ValueAsInt;
-            int hour = _systemTimeHourSpin.ValueAsInt;
-            int minute = _systemTimeMinuteSpin.ValueAsInt;
-
-            if (!DateTime.TryParse(year + "-" + month + "-" + day + " " + hour + ":" + minute, out DateTime newTime))
-            {
-                UpdateSystemTimeSpinners();
-
-                return;
-            }
-
-            newTime = newTime.AddSeconds(DateTime.Now.Second).AddMilliseconds(DateTime.Now.Millisecond);
-
-            long systemTimeOffset = (long)Math.Ceiling((newTime - DateTime.Now).TotalMinutes) * 60L;
-
-            if (_systemTimeOffset != systemTimeOffset)
-            {
-                _systemTimeOffset = systemTimeOffset;
-                UpdateSystemTimeSpinners();
-            }
-        }
-
-        private void AddDir_Pressed(object sender, EventArgs args)
-        {
-            if (Directory.Exists(_addGameDirBox.Buffer.Text))
-            {
-                _gameDirsBoxStore.AppendValues(_addGameDirBox.Buffer.Text);
-                _directoryChanged = true;
-            }
-            else
-            {
-                FileChooserNative fileChooser = new("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Add", "Cancel")
-                {
-                    SelectMultiple = true,
-                };
-
-                if (fileChooser.Run() == (int)ResponseType.Accept)
-                {
-                    _directoryChanged = false;
-                    foreach (string directory in fileChooser.Filenames)
-                    {
-                        if (_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter))
-                        {
-                            do
-                            {
-                                if (directory.Equals((string)_gameDirsBoxStore.GetValue(treeIter, 0)))
-                                {
-                                    break;
-                                }
-                            } while (_gameDirsBoxStore.IterNext(ref treeIter));
-                        }
-
-                        if (!_directoryChanged)
-                        {
-                            _gameDirsBoxStore.AppendValues(directory);
-                        }
-                    }
-
-                    _directoryChanged = true;
-                }
-
-                fileChooser.Dispose();
-            }
-
-            _addGameDirBox.Buffer.Text = "";
-
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-        }
-
-        private void RemoveDir_Pressed(object sender, EventArgs args)
-        {
-            TreeSelection selection = _gameDirsBox.Selection;
-
-            if (selection.GetSelected(out TreeIter treeIter))
-            {
-                _gameDirsBoxStore.Remove(ref treeIter);
-
-                _directoryChanged = true;
-            }
-
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-        }
-
-        private void CustThemeToggle_Activated(object sender, EventArgs args)
-        {
-            _custThemePath.Sensitive = _custThemeToggle.Active;
-            _custThemePathLabel.Sensitive = _custThemeToggle.Active;
-            _browseThemePath.Sensitive = _custThemeToggle.Active;
-        }
-
-        private void BrowseThemeDir_Pressed(object sender, EventArgs args)
-        {
-            using (FileChooserNative fileChooser = new("Choose the theme to load", this, FileChooserAction.Open, "Select", "Cancel"))
-            {
-                FileFilter filter = new()
-                {
-                    Name = "Theme Files",
-                };
-                filter.AddPattern("*.css");
-
-                fileChooser.AddFilter(filter);
-
-                if (fileChooser.Run() == (int)ResponseType.Accept)
-                {
-                    _custThemePath.Buffer.Text = fileChooser.Filename;
-                }
-            }
-
-            _browseThemePath.SetStateFlags(StateFlags.Normal, true);
-        }
-
-        private void ConfigureController_Pressed(object sender, PlayerIndex playerIndex)
-        {
-            ((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
-
-            ControllerWindow controllerWindow = new(_parent, playerIndex);
-
-            controllerWindow.SetSizeRequest((int)(controllerWindow.DefaultWidth * Program.WindowScaleFactor), (int)(controllerWindow.DefaultHeight * Program.WindowScaleFactor));
-            controllerWindow.Show();
-        }
-
-        private void VolumeSlider_OnChange(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.System.AudioVolume.Value = (float)(_audioVolumeSlider.Value / 100);
-        }
-
-        private void SaveToggle_Activated(object sender, EventArgs args)
-        {
-            SaveSettings();
-            Dispose();
-        }
-
-        private void ApplyToggle_Activated(object sender, EventArgs args)
-        {
-            SaveSettings();
-        }
-
-        private void CloseToggle_Activated(object sender, EventArgs args)
-        {
-            ConfigurationState.Instance.System.AudioVolume.Value = _previousVolumeLevel;
-            Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/SettingsWindow.glade b/src/Ryujinx/Ui/Windows/SettingsWindow.glade
deleted file mode 100644
index f0dbd6b6..00000000
--- a/src/Ryujinx/Ui/Windows/SettingsWindow.glade
+++ /dev/null
@@ -1,3221 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.40.0 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkAdjustment" id="_fsLogSpinAdjustment">
-    <property name="upper">3</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="_scalingFilterLevel">
-    <property name="upper">101</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">5</property>
-    <property name="page-size">1</property>
-  </object>
-  <object class="GtkAdjustment" id="_systemTimeDaySpinAdjustment">
-    <property name="lower">1</property>
-    <property name="upper">31</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">5</property>
-  </object>
-  <object class="GtkAdjustment" id="_systemTimeHourSpinAdjustment">
-    <property name="upper">23</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">5</property>
-  </object>
-  <object class="GtkAdjustment" id="_systemTimeMinuteSpinAdjustment">
-    <property name="upper">59</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">5</property>
-  </object>
-  <object class="GtkAdjustment" id="_systemTimeMonthSpinAdjustment">
-    <property name="lower">1</property>
-    <property name="upper">12</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">5</property>
-  </object>
-  <object class="GtkAdjustment" id="_systemTimeYearSpinAdjustment">
-    <property name="lower">2000</property>
-    <property name="upper">2060</property>
-    <property name="step-increment">1</property>
-    <property name="page-increment">10</property>
-  </object>
-  <object class="GtkEntryCompletion" id="_systemTimeZoneCompletion">
-    <property name="minimum-key-length">0</property>
-    <property name="inline-completion">True</property>
-    <property name="inline-selection">True</property>
-  </object>
-  <object class="GtkWindow" id="_settingsWin">
-    <property name="can-focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - Settings</property>
-    <property name="modal">True</property>
-    <property name="window-position">center</property>
-    <property name="default-width">650</property>
-    <property name="default-height">650</property>
-    <child>
-      <object class="GtkBox">
-        <property name="visible">True</property>
-        <property name="can-focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkScrolledWindow">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
-            <property name="shadow-type">in</property>
-            <child>
-              <object class="GtkViewport">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <child>
-                  <object class="GtkNotebook">
-                    <property name="visible">True</property>
-                    <property name="can-focus">True</property>
-                    <child>
-                      <object class="GtkBox" id="TabGeneral">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">10</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox" id="CatGeneral">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">General</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="General">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkCheckButton" id="_discordToggle">
-                                    <property name="label" translatable="yes">Enable Discord Rich Presence</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Choose whether or not to display Ryujinx on your "currently playing" Discord activity</property>
-                                    <property name="halign">start</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_checkUpdatesToggle">
-                                    <property name="label" translatable="yes">Check for Updates on Launch</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="halign">start</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_showConfirmExitToggle">
-                                    <property name="label" translatable="yes">Show "Confirm Exit" Dialog</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="halign">start</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="_hideCursorBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">Hide Cursor:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkRadioButton" id="_hideCursorNever">
-                                        <property name="label" translatable="yes">Never</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">False</property>
-                                        <property name="halign">start</property>
-                                        <property name="margin-top">5</property>
-                                        <property name="margin-bottom">5</property>
-                                        <property name="active">True</property>
-                                        <property name="draw-indicator">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkRadioButton" id="_hideCursorOnIdle">
-                                        <property name="label" translatable="yes">On Idle</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">False</property>
-                                        <property name="halign">start</property>
-                                        <property name="margin-top">5</property>
-                                        <property name="margin-bottom">5</property>
-                                        <property name="draw-indicator">True</property>
-                                        <property name="group">_hideCursorNever</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkRadioButton" id="_hideCursorAlways">
-                                        <property name="label" translatable="yes">Always</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">False</property>
-                                        <property name="halign">start</property>
-                                        <property name="margin-top">5</property>
-                                        <property name="margin-bottom">5</property>
-                                        <property name="draw-indicator">True</property>
-                                        <property name="group">_hideCursorNever</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">5</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatGameDir">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Game Directories</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkScrolledWindow">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="margin-bottom">10</property>
-                                    <property name="shadow-type">in</property>
-                                    <child>
-                                      <object class="GtkTreeView" id="_gameDirsBox">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="headers-visible">False</property>
-                                        <property name="headers-clickable">False</property>
-                                        <child internal-child="selection">
-                                          <object class="GtkTreeSelection"/>
-                                        </child>
-                                      </object>
-                                    </child>
-                                    <style>
-                                      <class name="GameDir"/>
-                                    </style>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkEntry" id="_addGameDirBox">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Enter a game directory to add to the list</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkToggleButton" id="_addDir">
-                                        <property name="label" translatable="yes">Add</property>
-                                        <property name="width-request">80</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">True</property>
-                                        <property name="tooltip-text" translatable="yes"> Add a game directory to the list</property>
-                                        <property name="margin-left">5</property>
-                                        <signal name="toggled" handler="AddDir_Pressed" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkToggleButton" id="_removeDir">
-                                        <property name="label" translatable="yes">Remove</property>
-                                        <property name="width-request">80</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">True</property>
-                                        <property name="tooltip-text" translatable="yes">Remove selected game directory</property>
-                                        <property name="margin-left">5</property>
-                                        <signal name="toggled" handler="RemoveDir_Pressed" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">4</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">5</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatThemes">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Themes</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkCheckButton" id="_custThemeToggle">
-                                    <property name="label" translatable="yes">Use Custom Theme</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Enable or disable custom themes in the GUI</property>
-                                    <property name="halign">start</property>
-                                    <property name="draw-indicator">True</property>
-                                    <signal name="toggled" handler="CustThemeToggle_Activated" swapped="no"/>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel" id="_custThemePathLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Path to custom GUI theme</property>
-                                        <property name="label" translatable="yes">Custom Theme Path:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkEntry" id="_custThemePath">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Path to custom GUI theme</property>
-                                        <property name="valign">center</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkToggleButton" id="_browseThemePath">
-                                        <property name="label" translatable="yes">Browse...</property>
-                                        <property name="width-request">80</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="receives-default">True</property>
-                                        <property name="tooltip-text" translatable="yes">Browse for a custom GUI theme</property>
-                                        <property name="margin-left">5</property>
-                                        <signal name="toggled" handler="BrowseThemeDir_Pressed" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">10</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">6</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">General</property>
-                      </object>
-                      <packing>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="TabInput">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">10</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-top">5</property>
-                            <property name="margin-bottom">5</property>
-                            <child>
-                              <object class="GtkCheckButton" id="_dockedModeToggle">
-                                <property name="label" translatable="yes">Enable Docked Mode</property>
-                                <property name="visible">True</property>
-                                <property name="can-focus">True</property>
-                                <property name="receives-default">False</property>
-                                <property name="tooltip-text" translatable="yes">Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.&#13;Configure player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.&#13;Leave ON if unsure.</property>
-                                <property name="draw-indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="padding">10</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="_directKeyboardAccess">
-                                <property name="label" translatable="yes">Direct Keyboard Access</property>
-                                <property name="visible">True</property>
-                                <property name="can-focus">True</property>
-                                <property name="receives-default">False</property>
-                                <property name="tooltip-text" translatable="yes">Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.</property>
-                                <property name="draw-indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="padding">10</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="_directMouseAccess">
-                                <property name="label" translatable="yes">Direct Mouse Access</property>
-                                <property name="visible">True</property>
-                                <property name="can-focus">True</property>
-                                <property name="receives-default">False</property>
-                                <property name="tooltip-text" translatable="yes">Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.</property>
-                                <property name="draw-indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="padding">10</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <!-- n-columns=5 n-rows=5 -->
-                          <object class="GtkGrid" id="ControllerGrid">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="halign">center</property>
-                            <property name="valign">center</property>
-                            <property name="column-spacing">20</property>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 1</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController1">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 3</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController3">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">4</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 2</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController2">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">2</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Handheld</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureControllerH">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">4</property>
-                                <property name="top-attach">4</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 6</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController6">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">4</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 5</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController5">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">2</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 7</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController7">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">4</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 4</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController4">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                    <property name="label" translatable="yes">Player 8</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkToggleButton" id="_configureController8">
-                                    <property name="label" translatable="yes">Configure</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">True</property>
-                                    <property name="margin-left">20</property>
-                                    <property name="margin-right">20</property>
-                                    <property name="margin-top">20</property>
-                                    <property name="margin-bottom">20</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left-attach">2</property>
-                                <property name="top-attach">4</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">3</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">3</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">3</property>
-                                <property name="top-attach">4</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">4</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">3</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">3</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">2</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">4</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">2</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkSeparator">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">4</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Input</property>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="TabSystem">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">10</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox" id="CatCore">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="valign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Core</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox" id="RegionBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System Region</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">System Region:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_systemRegionSelect">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System Region</property>
-                                        <property name="margin-left">5</property>
-                                        <items>
-                                          <item id="Japan" translatable="yes">Japan</item>
-                                          <item id="USA" translatable="yes">USA</item>
-                                          <item id="Europe" translatable="yes">Europe</item>
-                                          <item id="Australia" translatable="yes">Australia</item>
-                                          <item id="China" translatable="yes">China</item>
-                                          <item id="Korea" translatable="yes">Korea</item>
-                                          <item id="Taiwan" translatable="yes">Taiwan</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="LanguageBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System Language</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">System Language:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_systemLanguageSelect">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System Language</property>
-                                        <items>
-                                          <item id="AmericanEnglish" translatable="yes">American English</item>
-                                          <item id="BritishEnglish" translatable="yes">British English</item>
-                                          <item id="CanadianFrench" translatable="yes">Canadian French</item>
-                                          <item id="Chinese" translatable="yes">Chinese</item>
-                                          <item id="Dutch" translatable="yes">Dutch</item>
-                                          <item id="French" translatable="yes">French</item>
-                                          <item id="German" translatable="yes">German</item>
-                                          <item id="Italian" translatable="yes">Italian</item>
-                                          <item id="Japanese" translatable="yes">Japanese</item>
-                                          <item id="Korean" translatable="yes">Korean</item>
-                                          <item id="LatinAmericanSpanish" translatable="yes">Latin American Spanish</item>
-                                          <item id="Portuguese" translatable="yes">Portuguese</item>
-                                          <item id="Russian" translatable="yes">Russian</item>
-                                          <item id="SimplifiedChinese" translatable="yes">Simplified Chinese</item>
-                                          <item id="Spanish" translatable="yes">Spanish</item>
-                                          <item id="Taiwanese" translatable="yes">Taiwanese</item>
-                                          <item id="TraditionalChinese" translatable="yes">Traditional Chinese</item>
-                                          <item id="BrazilianPortuguese" translatable="yes">Brazilian Portuguese</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="TimeZoneBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System TimeZone</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">System TimeZone:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkEntry" id="_systemTimeZoneEntry">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Change System TimeZone</property>
-                                        <property name="margin-left">5</property>
-                                        <property name="completion">_systemTimeZoneCompletion</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="TimeBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change System Time</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">System Time:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton" id="_systemTimeYearSpin">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="text" translatable="yes">2000</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="adjustment">_systemTimeYearSpinAdjustment</property>
-                                        <property name="wrap">True</property>
-                                        <property name="value">2000</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="halign">end</property>
-                                        <property name="label">-</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton" id="_systemTimeMonthSpin">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="text" translatable="yes">1</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="adjustment">_systemTimeMonthSpinAdjustment</property>
-                                        <property name="wrap">True</property>
-                                        <property name="value">1</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="halign">end</property>
-                                        <property name="label">-</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">4</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton" id="_systemTimeDaySpin">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="text" translatable="yes">1</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="adjustment">_systemTimeDaySpinAdjustment</property>
-                                        <property name="wrap">True</property>
-                                        <property name="value">1</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">5</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton" id="_systemTimeHourSpin">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="text" translatable="yes">0</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="adjustment">_systemTimeHourSpinAdjustment</property>
-                                        <property name="wrap">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">6</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="halign">end</property>
-                                        <property name="label">:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">7</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton" id="_systemTimeMinuteSpin">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="text" translatable="yes">0</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="adjustment">_systemTimeMinuteSpinAdjustment</property>
-                                        <property name="wrap">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">8</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_vSyncToggle">
-                                    <property name="label" translatable="yes">Enable VSync</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.&#13;Can be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.&#13;Leave ON if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_ptcToggle">
-                                    <property name="label" translatable="yes">Enable PPTC (Profiled Persistent Translation Cache)</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Saves translated JIT functions so that they do not need to be translated every time the game loads.&#13;Reduces stuttering and significantly speeds up boot times after the first boot of a game.&#13;Leave ON if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">6</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_internetToggle">
-                                    <property name="label" translatable="yes">Enable Guest Internet Access</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Allows the emulated application to connect to the Internet.&#13;Games with a LAN mode can connect to each other when this is enabled and the systems are connected to the same access point. This includes real consoles as well.&#13;Does NOT allow connecting to Nintendo servers. May cause crashing in certain games that try to connect to the Internet.&#13;Leave OFF if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">7</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_fsicToggle">
-                                    <property name="label" translatable="yes">Enable FS Integrity Checks</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.&#13;Has no impact on performance and is meant to help troubleshooting.&#13;Leave ON if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">8</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="_audioBackendBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="tooltip-text" translatable="yes">Changes the backend used to render audio.&#13;SDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.&#13;Set to SDL2 if unsure.</property>
-                                    <property name="halign">end</property>
-                                    <property name="margin-right">5</property>
-                                    <property name="label" translatable="yes">Audio Backend: </property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="padding">5</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="_memoryManagerBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="tooltip-text" translatable="yes">Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.&#13;Set to HOST UNCHECKED if unsure.</property>
-                                    <property name="halign">end</property>
-                                    <property name="margin-right">5</property>
-                                    <property name="label" translatable="yes">Memory Manager Mode: </property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkRadioButton" id="_mmSoftware">
-                                    <property name="label" translatable="yes">Software</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Use a software page table for address translation. Highest accuracy but slowest performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkRadioButton" id="_mmHost">
-                                    <property name="label" translatable="yes">Host (fast)</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Directly map memory in the host address space. Much faster JIT compilation and execution.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                    <property name="group">_mmSoftware</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkRadioButton" id="_mmHostUnsafe">
-                                    <property name="label" translatable="yes">Host Unchecked (fastest, unsafe)</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                    <property name="group">_mmSoftware</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">5</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="padding">5</property>
-                                <property name="position">3</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatHacks">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="valign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="label" translatable="yes">Hacks</property>
-                                    <attributes>
-                                      <attribute name="weight" value="bold"/>
-                                    </attributes>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="label" translatable="yes"> (may cause instability)</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkCheckButton" id="_expandRamToggle">
-                                    <property name="label" translatable="yes">Use alternative memory layout (Developers)</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Utilizes an alternative MemoryMode layout to mimic a Switch development model.&#13;This is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.&#13;Leave OFF if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_ignoreToggle">
-                                    <property name="label" translatable="yes">Ignore Missing Services</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.&#13;Leave OFF if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">4</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="halign">end</property>
-                        <property name="label" translatable="yes">System</property>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="TabGraphics">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox" id="CatFeatures">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-left">5</property>
-                                <property name="margin-right">5</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Features</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="FeaturesOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Executes graphics backend commands on a second thread.&#13;Speeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.&#13;Set to AUTO if unsure.</property>
-                                        <property name="label" translatable="yes">Graphics Backend Multithreading:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_galThreading">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Executes graphics backend commands on a second thread.&#13;Speeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.&#13;Set to AUTO if unsure.</property>
-                                        <property name="active-id">-1</property>
-                                        <items>
-                                          <item id="Auto" translatable="yes">Auto</item>
-                                          <item id="Off" translatable="yes">Off</item>
-                                          <item id="On" translatable="yes">On</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Graphics Backend to use</property>
-                                        <property name="label" translatable="yes">Graphics Backend:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_graphicsBackend">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Graphics Backend to use</property>
-                                        <property name="active-id">-1</property>
-                                        <items>
-                                          <item id="0" translatable="yes">Vulkan</item>
-                                          <item id="1" translatable="yes">OpenGL</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
-                                        <property name="label" translatable="yes">Preferred GPU:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_preferredGpu">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
-                                        <property name="active-id">-1</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatEnhancements">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-left">5</property>
-                                <property name="margin-right">5</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Enhancements</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="EnhancementOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkCheckButton" id="_shaderCacheToggle">
-                                    <property name="label" translatable="yes">Enable Shader Cache</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Saves a disk shader cache which reduces stuttering in subsequent runs.&#13;Leave ON if unsure.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_textureRecompressionToggle">
-                                    <property name="label" translatable="yes">Enable Texture Recompression</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Enables or disables Texture Recompression. Reduces VRAM usage at the cost of texture quality, and may also increase stuttering</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_macroHLEToggle">
-                                    <property name="label" translatable="yes">Enable Macro HLE</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Enables or disables high-level emulation of Macro code. Improves performance but may cause graphical glitches in some games</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Resolution Scale applied to applicable render targets.</property>
-                                        <property name="label" translatable="yes">Resolution Scale:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_resScaleCombo">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Resolution Scale applied to applicable render targets.</property>
-                                        <property name="active-id">1</property>
-                                        <items>
-                                          <item id="1" translatable="yes">Native (720p/1080p)</item>
-                                          <item id="2" translatable="yes">2x (1440p/2160p)</item>
-                                          <item id="3" translatable="yes">3x (2160p/3240p)</item>
-                                          <item id="4" translatable="yes">4x (2880p/4320p)</item>
-                                          <item id="-1" translatable="yes">Custom (not recommended)</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkEntry" id="_resScaleText">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.</property>
-                                        <property name="valign">center</property>
-                                        <property name="caps-lock-warning">False</property>
-                                        <property name="placeholder-text">1.0</property>
-                                        <property name="input-purpose">number</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Applies a final effect to the game render</property>
-                                        <property name="label" translatable="yes">Post Processing Effect:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_antiAliasing">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Applies anti-aliasing to the game render</property>
-                                        <property name="active-id">1</property>
-                                        <items>
-                                          <item id="0" translatable="yes">None</item>
-                                          <item id="1" translatable="yes">FXAA</item>
-                                          <item id="2" translatable="yes">SMAA Low</item>
-                                          <item id="3" translatable="yes">SMAA Medium</item>
-                                          <item id="4" translatable="yes">SMAA High</item>
-                                          <item id="5" translatable="yes">SMAA Ultra</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="width-request">100</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Enables Framebuffer Upscaling</property>
-                                        <property name="label" translatable="yes">Upscale: </property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_scalingFilter">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Enables Framebuffer Upscaling</property>
-                                        <property name="active-id">1</property>
-                                        <items>
-                                          <item id="0" translatable="yes">Bilinear</item>
-                                          <item id="1" translatable="yes">Nearest</item>
-                                          <item id="2" translatable="yes">FSR</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkScale" id="_scalingFilterSlider">
-                                        <property name="width-request">200</property>
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="margin-start">5</property>
-                                        <property name="adjustment">_scalingFilterLevel</property>
-                                        <property name="round-digits">1</property>
-                                        <property name="value-pos">right</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">5</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Level of Anisotropic Filtering (set to Auto to use the value requested by the game)</property>
-                                        <property name="label" translatable="yes">Anisotropic Filtering:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_anisotropy">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Level of Anisotropic Filtering (set to Auto to use the value requested by the game)</property>
-                                        <property name="active-id">-1</property>
-                                        <items>
-                                          <item id="-1" translatable="yes">Auto</item>
-                                          <item id="2" translatable="yes">2x</item>
-                                          <item id="4" translatable="yes">4x</item>
-                                          <item id="8" translatable="yes">8x</item>
-                                          <item id="16" translatable="yes">16x</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">6</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Aspect Ratio applied to the renderer window.</property>
-                                        <property name="label" translatable="yes">Aspect Ratio:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_aspectRatio">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Aspect Ratio applied to the renderer window.</property>
-                                        <property name="active-id">1</property>
-                                        <items>
-                                          <item id="0" translatable="yes">4:3</item>
-                                          <item id="1" translatable="yes">16:9</item>
-                                          <item id="2" translatable="yes">16:10</item>
-                                          <item id="3" translatable="yes">21:9</item>
-                                          <item id="4" translatable="yes">32:9</item>
-                                          <item id="5" translatable="yes">Stretch to Fit Window</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">7</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkSeparator">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatDev">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-left">5</property>
-                                <property name="margin-right">5</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Developer Options</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="DevOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Graphics Shaders Dump Path</property>
-                                        <property name="label" translatable="yes">Graphics Shaders Dump Path:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkEntry" id="_graphicsShadersDumpPath">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Graphics Shaders Dump Path</property>
-                                        <property name="valign">center</property>
-                                        <property name="caps-lock-warning">False</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">4</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Graphics</property>
-                      </object>
-                      <packing>
-                        <property name="position">3</property>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="TabLogging">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">10</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox" id="CatLogging">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Logging</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="LogggingOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="valign">start</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkCheckButton" id="_fileLogToggle">
-                                    <property name="label" translatable="yes">Enable Logging to File</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Saves console logging to a log file on disk. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_stubLogToggle">
-                                    <property name="label" translatable="yes">Enable Stub Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints stub log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_infoLogToggle">
-                                    <property name="label" translatable="yes">Enable Info Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints info log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_warningLogToggle">
-                                    <property name="label" translatable="yes">Enable Warning Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints warning log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">5</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_errorLogToggle">
-                                    <property name="label" translatable="yes">Enable Error Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints error log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">6</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_guestLogToggle">
-                                    <property name="label" translatable="yes">Enable Guest Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints guest log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">7</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_fsAccessLogToggle">
-                                    <property name="label" translatable="yes">Enable Fs Access Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">8</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
-                                        <property name="label" translatable="yes">Fs Global Access Log Mode:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkSpinButton">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">True</property>
-                                        <property name="tooltip-text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
-                                        <property name="text" translatable="yes">0</property>
-                                        <property name="adjustment">_fsLogSpinAdjustment</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">9</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatDevLogging">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="margin-top">10</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="tooltip-text" translatable="yes">Use with care</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Developer Options (WARNING: Will reduce performance)</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="DevLoggingOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="valign">start</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="margin-top">5</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Requires appropriate log levels enabled.</property>
-                                        <property name="label" translatable="yes">Graphics Backend Log Level</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">22</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_graphicsDebugLevel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Requires appropriate log levels enabled.</property>
-                                        <property name="margin-left">5</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">22</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_debugLogToggle">
-                                    <property name="label" translatable="yes">Enable Debug Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints debug log messages in the console.&#13;Only use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">21</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="_traceLogToggle">
-                                    <property name="label" translatable="yes">Enable Trace Logs</property>
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">True</property>
-                                    <property name="receives-default">False</property>
-                                    <property name="tooltip-text" translatable="yes">Prints trace log messages in the console. Does not affect performance.</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-top">5</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="draw-indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">22</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">22</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">4</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Logging</property>
-                      </object>
-                      <packing>
-                        <property name="position">4</property>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="TabMultiplayer">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="margin-left">5</property>
-                        <property name="margin-right">10</property>
-                        <property name="margin-top">5</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkBox" id="CatMultiplayer">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="valign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">Multiplayer</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="MultiplayerOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="valign">start</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox" id="ModeBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change Multiplayer Mode</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">Mode:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_multiModeSelect">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">Change Multiplayer Mode</property>
-                                        <property name="active-id">Disabled</property>
-                                        <items>
-                                          <item id="Disabled" translatable="yes">Disabled</item>
-                                          <item id="LdnMitm" translatable="yes">ldn_mitm</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="CatLAN">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="valign">start</property>
-                            <property name="margin-left">5</property>
-                            <property name="margin-right">5</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="halign">start</property>
-                                <property name="margin-bottom">5</property>
-                                <property name="label" translatable="yes">LAN Mode</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkBox" id="LANOptions">
-                                <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="valign">start</property>
-                                <property name="margin-left">10</property>
-                                <property name="margin-right">10</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox" id="NetworkInterfaceBox">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <child>
-                                      <object class="GtkLabel">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">The network interface used for LAN/LDN features</property>
-                                        <property name="halign">end</property>
-                                        <property name="label" translatable="yes">Network Interface:</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="padding">5</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="_multiLanSelect">
-                                        <property name="visible">True</property>
-                                        <property name="can-focus">False</property>
-                                        <property name="tooltip-text" translatable="yes">The network interface used for LAN/LDN features</property>
-                                        <property name="active-id">0</property>
-                                        <items>
-                                          <item id="0" translatable="yes">Default</item>
-                                        </items>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="halign">start</property>
-                                    <property name="margin-bottom">5</property>
-                                    <property name="label" translatable="yes">To use LAN functionality in games, Enable Guest Internet Access must be checked in System.</property>
-                                    <property name="wrap">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="padding">5</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">5</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Multiplayer</property>
-                      </object>
-                      <packing>
-                        <property name="position">5</property>
-                        <property name="tab-fill">False</property>
-                      </packing>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButtonBox" id="_buttonBox">
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="margin-right">5</property>
-            <property name="margin-top">3</property>
-            <property name="margin-bottom">3</property>
-            <property name="spacing">5</property>
-            <property name="layout-style">end</property>
-            <child>
-              <object class="GtkToggleButton" id="SaveToggle">
-                <property name="label" translatable="yes">Save</property>
-                <property name="visible">True</property>
-                <property name="can-focus">True</property>
-                <property name="receives-default">True</property>
-                <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToggleButton" id="CloseToggle">
-                <property name="label" translatable="yes">Close</property>
-                <property name="visible">True</property>
-                <property name="can-focus">True</property>
-                <property name="receives-default">True</property>
-                <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton">
-                <property name="label" translatable="yes">Apply</property>
-                <property name="visible">True</property>
-                <property name="can-focus">True</property>
-                <property name="receives-default">True</property>
-                <signal name="clicked" handler="ApplyToggle_Activated" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
deleted file mode 100644
index 51918eea..00000000
--- a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
+++ /dev/null
@@ -1,206 +0,0 @@
-using Gtk;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Ns;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Utilities;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Widgets;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using GUI = Gtk.Builder.ObjectAttribute;
-using SpanHelpers = LibHac.Common.SpanHelpers;
-
-namespace Ryujinx.Ui.Windows
-{
-    public class TitleUpdateWindow : Window
-    {
-        private readonly MainWindow _parent;
-        private readonly VirtualFileSystem _virtualFileSystem;
-        private readonly string _titleId;
-        private readonly string _updateJsonPath;
-
-        private TitleUpdateMetadata _titleUpdateWindowData;
-
-        private readonly Dictionary<RadioButton, string> _radioButtonToPathDictionary;
-        private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-#pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier
-        [GUI] Label _baseTitleInfoLabel;
-        [GUI] Box _availableUpdatesBox;
-        [GUI] RadioButton _noUpdateRadioButton;
-#pragma warning restore CS0649, IDE0044
-
-        public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, titleId, titleName) { }
-
-        private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
-        {
-            _parent = parent;
-
-            builder.Autoconnect(this);
-
-            _titleId = titleId;
-            _virtualFileSystem = virtualFileSystem;
-            _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json");
-            _radioButtonToPathDictionary = new Dictionary<RadioButton, string>();
-
-            try
-            {
-                _titleUpdateWindowData = JsonHelper.DeserializeFromFile(_updateJsonPath, _serializerContext.TitleUpdateMetadata);
-            }
-            catch
-            {
-                _titleUpdateWindowData = new TitleUpdateMetadata
-                {
-                    Selected = "",
-                    Paths = new List<string>(),
-                };
-            }
-
-            _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]";
-
-            foreach (string path in _titleUpdateWindowData.Paths)
-            {
-                AddUpdate(path);
-            }
-
-            if (_titleUpdateWindowData.Selected == "")
-            {
-                _noUpdateRadioButton.Active = true;
-            }
-            else
-            {
-                foreach ((RadioButton update, var _) in _radioButtonToPathDictionary.Where(keyValuePair => keyValuePair.Value == _titleUpdateWindowData.Selected))
-                {
-                    update.Active = true;
-                }
-            }
-        }
-
-        private void AddUpdate(string path)
-        {
-            if (File.Exists(path))
-            {
-                using FileStream file = new(path, FileMode.Open, FileAccess.Read);
-
-                PartitionFileSystem nsp = new();
-                nsp.Initialize(file.AsStorage()).ThrowIfFailure();
-
-                try
-                {
-                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);
-
-                    if (controlNca != null && patchNca != null)
-                    {
-                        ApplicationControlProperty controlData = new();
-
-                        using var nacpFile = new UniqueRef<IFile>();
-
-                        controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-                        nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
-
-                        RadioButton radioButton = new($"Version {controlData.DisplayVersionString.ToString()} - {path}");
-                        radioButton.JoinGroup(_noUpdateRadioButton);
-
-                        _availableUpdatesBox.Add(radioButton);
-                        _radioButtonToPathDictionary.Add(radioButton, path);
-
-                        radioButton.Show();
-                        radioButton.Active = true;
-                    }
-                    else
-                    {
-                        GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
-                    }
-                }
-                catch (Exception exception)
-                {
-                    GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
-                }
-            }
-        }
-
-        private void RemoveUpdates(bool removeSelectedOnly = false)
-        {
-            foreach (RadioButton radioButton in _noUpdateRadioButton.Group)
-            {
-                if (radioButton.Label != "No Update" && (!removeSelectedOnly || radioButton.Active))
-                {
-                    _availableUpdatesBox.Remove(radioButton);
-                    _radioButtonToPathDictionary.Remove(radioButton);
-                    radioButton.Dispose();
-                }
-            }
-        }
-
-        private void AddButton_Clicked(object sender, EventArgs args)
-        {
-            using FileChooserNative fileChooser = new("Select update files", this, FileChooserAction.Open, "Add", "Cancel");
-
-            fileChooser.SelectMultiple = true;
-
-            FileFilter filter = new()
-            {
-                Name = "Switch Game Updates",
-            };
-            filter.AddPattern("*.nsp");
-
-            fileChooser.AddFilter(filter);
-
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                foreach (string path in fileChooser.Filenames)
-                {
-                    AddUpdate(path);
-                }
-            }
-        }
-
-        private void RemoveButton_Clicked(object sender, EventArgs args)
-        {
-            RemoveUpdates(true);
-        }
-
-        private void RemoveAllButton_Clicked(object sender, EventArgs args)
-        {
-            RemoveUpdates();
-        }
-
-        private void SaveButton_Clicked(object sender, EventArgs args)
-        {
-            _titleUpdateWindowData.Paths.Clear();
-            _titleUpdateWindowData.Selected = "";
-
-            foreach (string paths in _radioButtonToPathDictionary.Values)
-            {
-                _titleUpdateWindowData.Paths.Add(paths);
-            }
-
-            foreach (RadioButton radioButton in _noUpdateRadioButton.Group)
-            {
-                if (radioButton.Active)
-                {
-                    _titleUpdateWindowData.Selected = _radioButtonToPathDictionary.TryGetValue(radioButton, out string updatePath) ? updatePath : "";
-                }
-            }
-
-            JsonHelper.SerializeToFile(_updateJsonPath, _titleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
-
-            _parent.UpdateGameTable();
-
-            Dispose();
-        }
-
-        private void CancelButton_Clicked(object sender, EventArgs args)
-        {
-            Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.glade b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.glade
deleted file mode 100644
index cfbac86d..00000000
--- a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.glade
+++ /dev/null
@@ -1,214 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.36.0 -->
-<interface>
-  <requires lib="gtk+" version="3.20"/>
-  <object class="GtkWindow" id="_titleUpdateWindow">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Ryujinx - Title Update Manager</property>
-    <property name="modal">True</property>
-    <property name="window_position">center</property>
-    <property name="default_width">550</property>
-    <property name="default_height">250</property>
-    <child>
-      <object class="GtkBox" id="MainBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkBox" id="UpdatesBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkLabel" id="_baseTitleInfoLabel">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="label" translatable="yes">Available Updates</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="margin_left">10</property>
-                <property name="margin_right">10</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkViewport">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkBox" id="_availableUpdatesBox">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkRadioButton" id="_noUpdateRadioButton">
-                            <property name="label" translatable="yes">No Update</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkButtonBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="layout_style">start</property>
-                <child>
-                  <object class="GtkButton" id="_addUpdate">
-                    <property name="label" translatable="yes">Add</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Adds an update to this list</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="AddButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_removeUpdate">
-                    <property name="label" translatable="yes">Remove</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Removes the selected update</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="RemoveButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_removeAllButton">
-                    <property name="label" translatable="yes">Remove All</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Removes all the updates</property>
-                    <property name="margin_left">10</property>
-                    <signal name="clicked" handler="RemoveAllButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButtonBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_top">10</property>
-                <property name="margin_bottom">10</property>
-                <property name="layout_style">end</property>
-                <child>
-                  <object class="GtkButton" id="_saveButton">
-                    <property name="label" translatable="yes">Save</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="SaveButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="_cancelButton">
-                    <property name="label" translatable="yes">Cancel</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="margin_right">10</property>
-                    <property name="margin_top">2</property>
-                    <property name="margin_bottom">2</property>
-                    <signal name="clicked" handler="CancelButton_Clicked" swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
-  </object>
-</interface>
diff --git a/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.Designer.cs b/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.Designer.cs
deleted file mode 100644
index 804bd3fb..00000000
--- a/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.Designer.cs
+++ /dev/null
@@ -1,255 +0,0 @@
-using Gtk;
-using Pango;
-using System;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class UserProfilesManagerWindow : Window
-    {
-        private Box _mainBox;
-        private Label _selectedLabel;
-        private Box _selectedUserBox;
-        private Image _selectedUserImage;
-        private Box _selectedUserInfoBox;
-        private Entry _selectedUserNameEntry;
-        private Label _selectedUserIdLabel;
-        private Box _selectedUserButtonsBox;
-        private Button _saveProfileNameButton;
-        private Button _changeProfileImageButton;
-        private Box _usersTreeViewBox;
-        private Label _availableUsersLabel;
-        private ScrolledWindow _usersTreeViewWindow;
-        private ListStore _tableStore;
-        private TreeView _usersTreeView;
-        private Box _bottomBox;
-        private Button _addButton;
-        private Button _deleteButton;
-        private Button _closeButton;
-
-        private void InitializeComponent()
-        {
-            //
-            // UserProfilesManagerWindow
-            //
-            CanFocus = false;
-            Resizable = false;
-            Modal = true;
-            WindowPosition = WindowPosition.Center;
-            DefaultWidth = 620;
-            DefaultHeight = 548;
-            TypeHint = Gdk.WindowTypeHint.Dialog;
-
-            //
-            // _mainBox
-            //
-            _mainBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _selectedLabel
-            //
-            _selectedLabel = new Label("Selected User Profile:")
-            {
-                Margin = 15,
-                Attributes = new AttrList(),
-                Halign = Align.Start,
-            };
-            _selectedLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
-
-            //
-            // _viewBox
-            //
-            _usersTreeViewBox = new Box(Orientation.Vertical, 0);
-
-            //
-            // _SelectedUserBox
-            //
-            _selectedUserBox = new Box(Orientation.Horizontal, 0)
-            {
-                MarginStart = 30,
-            };
-
-            //
-            // _selectedUserImage
-            //
-            _selectedUserImage = new Image();
-
-            //
-            // _selectedUserInfoBox
-            //
-            _selectedUserInfoBox = new Box(Orientation.Vertical, 0)
-            {
-                Homogeneous = true,
-            };
-
-            //
-            // _selectedUserNameEntry
-            //
-            _selectedUserNameEntry = new Entry("")
-            {
-                MarginStart = 15,
-                MaxLength = (int)MaxProfileNameLength,
-            };
-            _selectedUserNameEntry.KeyReleaseEvent += SelectedUserNameEntry_KeyReleaseEvent;
-
-            //
-            // _selectedUserIdLabel
-            //
-            _selectedUserIdLabel = new Label("")
-            {
-                MarginTop = 15,
-                MarginStart = 15,
-            };
-
-            //
-            // _selectedUserButtonsBox
-            //
-            _selectedUserButtonsBox = new Box(Orientation.Vertical, 0)
-            {
-                MarginEnd = 30,
-            };
-
-            //
-            // _saveProfileNameButton
-            //
-            _saveProfileNameButton = new Button()
-            {
-                Label = "Save Profile Name",
-                CanFocus = true,
-                ReceivesDefault = true,
-                Sensitive = false,
-            };
-            _saveProfileNameButton.Clicked += EditProfileNameButton_Pressed;
-
-            //
-            // _changeProfileImageButton
-            //
-            _changeProfileImageButton = new Button()
-            {
-                Label = "Change Profile Image",
-                CanFocus = true,
-                ReceivesDefault = true,
-                MarginTop = 10,
-            };
-            _changeProfileImageButton.Clicked += ChangeProfileImageButton_Pressed;
-
-            //
-            // _availableUsersLabel
-            //
-            _availableUsersLabel = new Label("Available User Profiles:")
-            {
-                Margin = 15,
-                Attributes = new AttrList(),
-                Halign = Align.Start,
-            };
-            _availableUsersLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
-
-            //
-            // _usersTreeViewWindow
-            //
-            _usersTreeViewWindow = new ScrolledWindow()
-            {
-                ShadowType = ShadowType.In,
-                CanFocus = true,
-                Expand = true,
-                MarginStart = 30,
-                MarginEnd = 30,
-                MarginBottom = 15,
-            };
-
-            //
-            // _tableStore
-            //
-            _tableStore = new ListStore(typeof(bool), typeof(Gdk.Pixbuf), typeof(string), typeof(Gdk.RGBA));
-
-            //
-            // _usersTreeView
-            //
-            _usersTreeView = new TreeView(_tableStore)
-            {
-                HoverSelection = true,
-                HeadersVisible = false,
-            };
-            _usersTreeView.RowActivated += UsersTreeView_Activated;
-
-            //
-            // _bottomBox
-            //
-            _bottomBox = new Box(Orientation.Horizontal, 0)
-            {
-                MarginStart = 30,
-                MarginEnd = 30,
-                MarginBottom = 15,
-            };
-
-            //
-            // _addButton
-            //
-            _addButton = new Button()
-            {
-                Label = "Add New Profile",
-                CanFocus = true,
-                ReceivesDefault = true,
-                HeightRequest = 35,
-            };
-            _addButton.Clicked += AddButton_Pressed;
-
-            //
-            // _deleteButton
-            //
-            _deleteButton = new Button()
-            {
-                Label = "Delete Selected Profile",
-                CanFocus = true,
-                ReceivesDefault = true,
-                HeightRequest = 35,
-                MarginStart = 10,
-            };
-            _deleteButton.Clicked += DeleteButton_Pressed;
-
-            //
-            // _closeButton
-            //
-            _closeButton = new Button()
-            {
-                Label = "Close",
-                CanFocus = true,
-                ReceivesDefault = true,
-                HeightRequest = 35,
-                WidthRequest = 80,
-            };
-            _closeButton.Clicked += CloseButton_Pressed;
-
-            ShowComponent();
-        }
-
-        private void ShowComponent()
-        {
-            _usersTreeViewWindow.Add(_usersTreeView);
-
-            _usersTreeViewBox.Add(_usersTreeViewWindow);
-            _bottomBox.PackStart(_addButton, false, false, 0);
-            _bottomBox.PackStart(_deleteButton, false, false, 0);
-            _bottomBox.PackEnd(_closeButton, false, false, 0);
-
-            _selectedUserInfoBox.Add(_selectedUserNameEntry);
-            _selectedUserInfoBox.Add(_selectedUserIdLabel);
-
-            _selectedUserButtonsBox.Add(_saveProfileNameButton);
-            _selectedUserButtonsBox.Add(_changeProfileImageButton);
-
-            _selectedUserBox.Add(_selectedUserImage);
-            _selectedUserBox.PackStart(_selectedUserInfoBox, false, false, 0);
-            _selectedUserBox.PackEnd(_selectedUserButtonsBox, false, false, 0);
-
-            _mainBox.PackStart(_selectedLabel, false, false, 0);
-            _mainBox.PackStart(_selectedUserBox, false, true, 0);
-            _mainBox.PackStart(_availableUsersLabel, false, false, 0);
-            _mainBox.Add(_usersTreeViewBox);
-            _mainBox.Add(_bottomBox);
-
-            Add(_mainBox);
-
-            ShowAll();
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.cs b/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.cs
deleted file mode 100644
index 3d503f64..00000000
--- a/src/Ryujinx/Ui/Windows/UserProfilesManagerWindow.cs
+++ /dev/null
@@ -1,328 +0,0 @@
-using Gtk;
-using Ryujinx.Common.Memory;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Widgets;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using Image = SixLabors.ImageSharp.Image;
-
-namespace Ryujinx.Ui.Windows
-{
-    public partial class UserProfilesManagerWindow : Window
-    {
-        private const uint MaxProfileNameLength = 0x20;
-
-        private readonly AccountManager _accountManager;
-        private readonly ContentManager _contentManager;
-
-        private byte[] _bufferImageProfile;
-        private string _tempNewProfileName;
-
-        private Gdk.RGBA _selectedColor;
-
-        private readonly ManualResetEvent _avatarsPreloadingEvent = new(false);
-
-        public UserProfilesManagerWindow(AccountManager accountManager, ContentManager contentManager, VirtualFileSystem virtualFileSystem) : base($"Ryujinx {Program.Version} - Manage User Profiles")
-        {
-            Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
-
-            InitializeComponent();
-
-            _selectedColor.Red = 0.212;
-            _selectedColor.Green = 0.843;
-            _selectedColor.Blue = 0.718;
-            _selectedColor.Alpha = 1;
-
-            _accountManager = accountManager;
-            _contentManager = contentManager;
-
-            CellRendererToggle userSelectedToggle = new();
-            userSelectedToggle.Toggled += UserSelectedToggle_Toggled;
-
-            // NOTE: Uncomment following line when multiple selection of user profiles is supported.
-            //_usersTreeView.AppendColumn("Selected",  userSelectedToggle,       "active", 0);
-            _usersTreeView.AppendColumn("User Icon", new CellRendererPixbuf(), "pixbuf", 1);
-            _usersTreeView.AppendColumn("User Info", new CellRendererText(), "text", 2, "background-rgba", 3);
-
-            _tableStore.SetSortColumnId(0, SortType.Descending);
-
-            RefreshList();
-
-            if (_contentManager.GetCurrentFirmwareVersion() != null)
-            {
-                Task.Run(() =>
-                {
-                    AvatarWindow.PreloadAvatars(contentManager, virtualFileSystem);
-                    _avatarsPreloadingEvent.Set();
-                });
-            }
-        }
-
-        public void RefreshList()
-        {
-            _tableStore.Clear();
-
-            foreach (UserProfile userProfile in _accountManager.GetAllUsers())
-            {
-                _tableStore.AppendValues(userProfile.AccountState == AccountState.Open, new Gdk.Pixbuf(userProfile.Image, 96, 96), $"{userProfile.Name}\n{userProfile.UserId}", Gdk.RGBA.Zero);
-
-                if (userProfile.AccountState == AccountState.Open)
-                {
-                    _selectedUserImage.Pixbuf = new Gdk.Pixbuf(userProfile.Image, 96, 96);
-                    _selectedUserIdLabel.Text = userProfile.UserId.ToString();
-                    _selectedUserNameEntry.Text = userProfile.Name;
-
-                    _deleteButton.Sensitive = userProfile.UserId != AccountManager.DefaultUserId;
-
-                    _usersTreeView.Model.GetIterFirst(out TreeIter firstIter);
-                    _tableStore.SetValue(firstIter, 3, _selectedColor);
-                }
-            }
-        }
-
-        //
-        // Events
-        //
-
-        private void UsersTreeView_Activated(object o, RowActivatedArgs args)
-        {
-            SelectUserTreeView();
-        }
-
-        private void UserSelectedToggle_Toggled(object o, ToggledArgs args)
-        {
-            SelectUserTreeView();
-        }
-
-        private void SelectUserTreeView()
-        {
-            // Get selected item informations.
-            _usersTreeView.Selection.GetSelected(out TreeIter selectedIter);
-
-            Gdk.Pixbuf userPicture = (Gdk.Pixbuf)_tableStore.GetValue(selectedIter, 1);
-
-            string userName = _tableStore.GetValue(selectedIter, 2).ToString().Split("\n")[0];
-            string userId = _tableStore.GetValue(selectedIter, 2).ToString().Split("\n")[1];
-
-            // Unselect the first user.
-            _usersTreeView.Model.GetIterFirst(out TreeIter firstIter);
-            _tableStore.SetValue(firstIter, 0, false);
-            _tableStore.SetValue(firstIter, 3, Gdk.RGBA.Zero);
-
-            // Set new informations.
-            _tableStore.SetValue(selectedIter, 0, true);
-
-            _selectedUserImage.Pixbuf = userPicture;
-            _selectedUserNameEntry.Text = userName;
-            _selectedUserIdLabel.Text = userId;
-            _saveProfileNameButton.Sensitive = false;
-
-            // Open the selected one.
-            _accountManager.OpenUser(new UserId(userId));
-
-            _deleteButton.Sensitive = userId != AccountManager.DefaultUserId.ToString();
-
-            _tableStore.SetValue(selectedIter, 3, _selectedColor);
-        }
-
-        private void SelectedUserNameEntry_KeyReleaseEvent(object o, KeyReleaseEventArgs args)
-        {
-            if (_saveProfileNameButton.Sensitive == false)
-            {
-                _saveProfileNameButton.Sensitive = true;
-            }
-        }
-
-        private void AddButton_Pressed(object sender, EventArgs e)
-        {
-            _tempNewProfileName = GtkDialog.CreateInputDialog(this, "Choose the Profile Name", "Please Enter a Profile Name", MaxProfileNameLength);
-
-            if (_tempNewProfileName != "")
-            {
-                SelectProfileImage(true);
-
-                if (_bufferImageProfile != null)
-                {
-                    AddUser();
-                }
-            }
-        }
-
-        private void DeleteButton_Pressed(object sender, EventArgs e)
-        {
-            if (GtkDialog.CreateChoiceDialog("Delete User Profile", "Are you sure you want to delete the profile ?", "Deleting this profile will also delete all associated save data."))
-            {
-                _accountManager.DeleteUser(GetSelectedUserId());
-
-                RefreshList();
-            }
-        }
-
-        private void EditProfileNameButton_Pressed(object sender, EventArgs e)
-        {
-            _saveProfileNameButton.Sensitive = false;
-
-            _accountManager.SetUserName(GetSelectedUserId(), _selectedUserNameEntry.Text);
-
-            RefreshList();
-        }
-
-        private void ProcessProfileImage(byte[] buffer)
-        {
-            using Image image = Image.Load(buffer);
-
-            image.Mutate(x => x.Resize(256, 256));
-
-            using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
-
-            image.SaveAsJpeg(streamJpg);
-
-            _bufferImageProfile = streamJpg.ToArray();
-        }
-
-        private void ProfileImageFileChooser()
-        {
-            FileChooserNative fileChooser = new("Import Custom Profile Image", this, FileChooserAction.Open, "Import", "Cancel")
-            {
-                SelectMultiple = false,
-            };
-
-            FileFilter filter = new()
-            {
-                Name = "Custom Profile Images",
-            };
-            filter.AddPattern("*.jpg");
-            filter.AddPattern("*.jpeg");
-            filter.AddPattern("*.png");
-            filter.AddPattern("*.bmp");
-
-            fileChooser.AddFilter(filter);
-
-            if (fileChooser.Run() == (int)ResponseType.Accept)
-            {
-                ProcessProfileImage(File.ReadAllBytes(fileChooser.Filename));
-            }
-
-            fileChooser.Dispose();
-        }
-
-        private void SelectProfileImage(bool newUser = false)
-        {
-            if (_contentManager.GetCurrentFirmwareVersion() == null)
-            {
-                ProfileImageFileChooser();
-            }
-            else
-            {
-                Dictionary<int, string> buttons = new()
-                {
-                    { 0, "Import Image File"      },
-                    { 1, "Select Firmware Avatar" },
-                };
-
-                ResponseType responseDialog = GtkDialog.CreateCustomDialog("Profile Image Selection",
-                                                                           "Choose a Profile Image",
-                                                                           "You may import a custom profile image, or select an avatar from the system firmware.",
-                                                                           buttons, MessageType.Question);
-
-                if (responseDialog == 0)
-                {
-                    ProfileImageFileChooser();
-                }
-                else if (responseDialog == (ResponseType)1)
-                {
-                    AvatarWindow avatarWindow = new()
-                    {
-                        NewUser = newUser,
-                    };
-
-                    avatarWindow.DeleteEvent += AvatarWindow_DeleteEvent;
-
-                    avatarWindow.SetSizeRequest((int)(avatarWindow.DefaultWidth * Program.WindowScaleFactor), (int)(avatarWindow.DefaultHeight * Program.WindowScaleFactor));
-                    avatarWindow.Show();
-                }
-            }
-        }
-
-        private void ChangeProfileImageButton_Pressed(object sender, EventArgs e)
-        {
-            if (_contentManager.GetCurrentFirmwareVersion() != null)
-            {
-                _avatarsPreloadingEvent.WaitOne();
-            }
-
-            SelectProfileImage();
-
-            if (_bufferImageProfile != null)
-            {
-                SetUserImage();
-            }
-        }
-
-        private void AvatarWindow_DeleteEvent(object sender, DeleteEventArgs args)
-        {
-            _bufferImageProfile = ((AvatarWindow)sender).SelectedProfileImage;
-
-            if (_bufferImageProfile != null)
-            {
-                if (((AvatarWindow)sender).NewUser)
-                {
-                    AddUser();
-                }
-                else
-                {
-                    SetUserImage();
-                }
-            }
-        }
-
-        private void AddUser()
-        {
-            _accountManager.AddUser(_tempNewProfileName, _bufferImageProfile);
-
-            _bufferImageProfile = null;
-            _tempNewProfileName = "";
-
-            RefreshList();
-        }
-
-        private void SetUserImage()
-        {
-            _accountManager.SetUserImage(GetSelectedUserId(), _bufferImageProfile);
-
-            _bufferImageProfile = null;
-
-            RefreshList();
-        }
-
-        private UserId GetSelectedUserId()
-        {
-            if (_usersTreeView.Model.GetIterFirst(out TreeIter iter))
-            {
-                do
-                {
-                    if ((bool)_tableStore.GetValue(iter, 0))
-                    {
-                        break;
-                    }
-                }
-                while (_usersTreeView.Model.IterNext(ref iter));
-            }
-
-            return new UserId(_tableStore.GetValue(iter, 2).ToString().Split("\n")[1]);
-        }
-
-        private void CloseButton_Pressed(object sender, EventArgs e)
-        {
-            Close();
-        }
-    }
-}
-- 
cgit v1.2.3-70-g09d2