From e839de50140f6f102d187db7cc5c106fbef38c9d Mon Sep 17 00:00:00 2001
From: pineappleEA <pineaea@gmail.com>
Date: Tue, 13 Apr 2021 00:32:26 +0200
Subject: [PATCH] early-access version 1591

---
 README.md                                     |    2 +-
 dist/qt_themes/default/style.qss              |  377 ----
 dist/qt_themes/qdarkstyle/style.qss           |  399 +---
 .../qdarkstyle_midnight_blue/style.qss        |  439 +----
 dist/yuzu.ico                                 |  Bin 25355 -> 23159 bytes
 dist/yuzu.svg                                 |    2 +-
 src/common/assert.cpp                         |    6 +-
 src/core/CMakeLists.txt                       |    1 -
 .../frontend/applets/software_keyboard.cpp    |  148 +-
 src/core/frontend/applets/software_keyboard.h |  114 +-
 src/core/frontend/input_interpreter.cpp       |   15 +-
 src/core/frontend/input_interpreter.h         |    3 -
 src/core/hle/kernel/hle_ipc.cpp               |    8 +-
 src/core/hle/kernel/hle_ipc.h                 |   10 -
 src/core/hle/kernel/k_thread.h                |    2 +-
 src/core/hle/kernel/kernel.cpp                |   41 +-
 src/core/hle/kernel/process.cpp               |   22 +-
 src/core/hle/service/am/am.cpp                |   79 +-
 src/core/hle/service/am/am.h                  |    1 -
 src/core/hle/service/am/applets/applets.cpp   |   18 +-
 src/core/hle/service/am/applets/applets.h     |   10 +-
 .../hle/service/am/applets/controller.cpp     |    5 +-
 src/core/hle/service/am/applets/controller.h  |    4 +-
 src/core/hle/service/am/applets/error.cpp     |    5 +-
 src/core/hle/service/am/applets/error.h       |    4 +-
 .../service/am/applets/general_backend.cpp    |   14 +-
 .../hle/service/am/applets/general_backend.h  |   11 +-
 .../hle/service/am/applets/profile_select.cpp |    4 +-
 .../hle/service/am/applets/profile_select.h   |    3 +-
 .../service/am/applets/software_keyboard.cpp  | 1167 ++---------
 .../service/am/applets/software_keyboard.h    |  187 +-
 .../hle/service/am/applets/web_browser.cpp    |    5 +-
 src/core/hle/service/am/applets/web_browser.h |    4 +-
 .../service/nvdrv/devices/nvhost_nvdec.cpp    |    1 -
 .../nvdrv/devices/nvhost_nvdec_common.cpp     |    8 +-
 .../nvdrv/devices/nvhost_nvdec_common.h       |    1 -
 .../hle/service/nvdrv/devices/nvhost_vic.cpp  |    5 +-
 src/input_common/sdl/sdl_impl.cpp             |   26 +-
 src/input_common/sdl/sdl_impl.h               |    4 -
 src/video_core/engines/shader_bytecode.h      |    4 -
 src/video_core/memory_manager.cpp             |   19 -
 src/video_core/memory_manager.h               |    8 -
 src/video_core/rasterizer_interface.h         |    6 -
 .../renderer_opengl/gl_arb_decompiler.cpp     |   82 +-
 .../renderer_opengl/gl_rasterizer.cpp         |   20 -
 .../renderer_opengl/gl_rasterizer.h           |    2 -
 .../renderer_opengl/gl_shader_decompiler.cpp  |  146 +-
 .../renderer_vulkan/vk_rasterizer.cpp         |   20 -
 .../renderer_vulkan/vk_rasterizer.h           |    2 -
 .../renderer_vulkan/vk_shader_decompiler.cpp  |  115 +-
 src/video_core/shader/control_flow.cpp        |  159 +-
 src/video_core/shader/control_flow.h          |   13 +-
 src/video_core/shader/decode.cpp              |  225 +--
 src/video_core/shader/decode/other.cpp        |   11 -
 src/video_core/shader/decode/texture.cpp      |    4 +-
 src/video_core/shader/node.h                  |   15 +-
 src/video_core/shader/node_helper.cpp         |    5 -
 src/video_core/shader/node_helper.h           |    3 -
 src/video_core/shader/shader_ir.h             |   95 +-
 src/yuzu/CMakeLists.txt                       |    4 -
 src/yuzu/applets/error.cpp                    |   22 +-
 src/yuzu/applets/error.h                      |    2 +-
 src/yuzu/applets/software_keyboard.cpp        | 1714 ++---------------
 src/yuzu/applets/software_keyboard.h          |  285 +--
 src/yuzu/discord_impl.cpp                     |    2 +-
 src/yuzu/main.cpp                             |  187 +-
 src/yuzu/main.h                               |   35 +-
 67 files changed, 777 insertions(+), 5583 deletions(-)

diff --git a/README.md b/README.md
index 8f4e6d47e..96e64acfb 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 yuzu emulator early access
 =============
 
-This is the source code for early-access 1588.
+This is the source code for early-access 1591.
 
 ## Legal Notice
 
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss
index 3bc92b69d..836dd25ca 100755
--- a/dist/qt_themes/default/style.qss
+++ b/dist/qt_themes/default/style.qss
@@ -281,380 +281,3 @@ QWidget#controllerPlayer7,
 QWidget#controllerPlayer8 {
     background: transparent;
 }
-
-QDialog#QtSoftwareKeyboardDialog,
-QStackedWidget#topOSK {
-    background: rgba(51, 51, 51, .9);
-}
-
-
-QDialog#OverlayDialog,
-QStackedWidget#stackedDialog {
-    background: rgba(51, 51, 51, .7);
-}
-
-QWidget#boxOSK,
-QWidget#lineOSK,
-QWidget#richDialog,
-QWidget#lineDialog {
-    background: transparent;
-}
-
-QStackedWidget#bottomOSK,
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-    background: rgba(240, 240, 240, 1);
-}
-
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-    margin: 5px;
-    border-radius: 6px;
-}
-
-QWidget#buttonsDialog,
-QWidget#buttonsRichDialog {
-    margin: 5px;
-    border-top: 2px solid rgba(44, 44, 44, 1);
-}
-
-QWidget#legendOSKnum {
-    border-top: 1px solid rgba(44, 44, 44, 1);
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical {
-    background: #cdcdcd;
-    width: 15px;
-    margin: 15px 3px 15px 3px;
-    border: 1px transparent;
-    border-radius: 4px;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal {
-    background: #cdcdcd;
-    height: 15px;
-    margin: 3px 15px 3px 15px;
-    border: 1px transparent;
-    border-radius: 4px;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle {
-    background: #fff;
-    border-radius: 4px;
-    min-height: 5px;
-    min-width: 5px;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line,
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page,
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page {
-    background: none;
-}
-
-QWidget#inputOSK {
-    border-bottom: 3px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputOSK QLineEdit {
-    background: transparent;
-    border: none;
-    color: #ccc;
-}
-
-QWidget#inputBoxOSK {
-    border: 2px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputBoxOSK QTextEdit {
-    background: transparent;
-    border: none;
-    color: #ccc;
-}
-
-QWidget#richDialog QTextBrowser {
-    background: transparent;
-    border: none;
-    padding: 35px 65px;
-}
-
-
-QWidget#lineOSK QLabel#label_header {
-    color: #f0f0f0;
-}
-
-QWidget#lineOSK QLabel#label_sub,
-QWidget#lineOSK QLabel#label_characters,
-QWidget#boxOSK QLabel#label_characters_box {
-    color: #ccc;
-}
-
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich {
-    color: #888;
-}
-
-QWidget#contentDialog QLabel#label_dialog {
-    padding: 20px 65px;
-}
-
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich {
-    padding: 0px 65px;
-}
-
-QDialog#OverlayDialog QPushButton {
-    color: rgba(49, 79, 239, 1);
-    background: transparent;
-    border: none;
-    padding: 0px;
-    min-width: 0px;
-}
-
-QDialog#OverlayDialog QPushButton:focus,
-QDialog#OverlayDialog QPushButton:hover {
-    color: rgba(49, 79, 239, 1);
-    background: rgba(255, 255, 255, 1);
-    border: 5px solid rgba(148, 250, 202, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#OverlayDialog QPushButton:pressed {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(150, 150, 150, 1);
-    border: 5px solid rgba(148, 250, 202, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton {
-    background: rgba(232, 232, 232, 1);
-    border: 2px solid rgba(240, 240, 240, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-    background: rgba(218, 218, 218, 1);
-    border: 2px solid rgba(240, 240, 240, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(44, 44, 44, 1);
-    border: 2px solid rgba(240, 240, 240, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(49, 79, 239, 1);
-    border: 2px solid rgba(240, 240, 240, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
-    color: rgba(0, 0, 0, 1);
-    background: rgba(255, 255, 255, 1);
-    border: 5px solid rgba(148, 250, 202, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(150, 150, 150, 1);
-    border: 5px solid rgba(148, 250, 202, 1);
-    border-radius: 6px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_B.png);
-    qproperty-icon: url(:/overlay/osk_button_backspace.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_Y.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_plus.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
-    background-position: left top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_shift_lock_off.png);
-    qproperty-icon: url(:/overlay/osk_button_shift.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
-    background-position: left top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_shift_lock_off.png);
-    qproperty-icon: url(:/overlay/osk_button_shift_on.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
-    padding-bottom: 7px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
-    background: transparent;
-    color: #ccc;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
-    image: url(:/overlay/button_L.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
-    image: url(:/overlay/arrow_left.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
-    image: url(:/overlay/button_R.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
-    image: url(:/overlay/arrow_right.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
-    image: url(:/overlay/button_press_stick.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
-    image: url(:/overlay/button_X.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
-    image: url(:/overlay/button_A.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-    color: rgba(164, 164, 164, 1);
-    background-color: rgba(218, 218, 218, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
-    color: rgba(164, 164, 164, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
-    background-image: url(:/overlay/osk_button_plus_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-    background-image: url(:/overlay/osk_button_B_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
-    background-image: url(:/overlay/osk_button_Y_disabled.png);
-}
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss
index 8ce6d75f7..2a1e8ddeb 100755
--- a/dist/qt_themes/qdarkstyle/style.qss
+++ b/dist/qt_themes/qdarkstyle/style.qss
@@ -1560,400 +1560,7 @@ QWidget#controllerPlayer8 {
     background: transparent;
 }
 
-QDialog#QtSoftwareKeyboardDialog,
-QStackedWidget#topOSK {
-    background: rgba(41, 41, 41, .9);
-}
-
-
-QDialog#OverlayDialog,
-QStackedWidget#stackedDialog {
-    background: rgba(41, 41, 41, .7);
-}
-
-QWidget#boxOSK,
-QWidget#lineOSK,
-QWidget#richDialog,
-QWidget#lineDialog {
-    background: transparent;
-}
-
-QStackedWidget#bottomOSK,
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-    background: rgba(71, 69, 71, 1);
-}
-
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-    margin: 5px;
-    border-radius: 6px;
-}
-
-QWidget#buttonsDialog,
-QWidget#buttonsRichDialog {
-    margin: 5px;
-    border-top: 2px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#legendOSKnum {
-    border-top: 1px solid rgba(255, 255, 255, 1);
-}
-
-QStackedWidget#stackedDialog QTextBrowser QWidget {
-    background: transparent;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar {
-    background: #2a2929;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
-    border-image: none;
-}
-
-QWidget#inputOSK {
-    border-bottom: 3px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputOSK QLineEdit {
-    background: transparent;
-    border: none;
-    color: #ccc;
-    padding: 0px;
-}
-
-QWidget#inputBoxOSK {
-    border: 2px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputBoxOSK QTextEdit {
-    background: transparent;
-    border: none;
-    color: #ccc;
-}
-
-QWidget#richDialog QTextBrowser {
-    background: transparent;
-    border: none;
-    color: #fff;
-    padding: 35px 65px;
-}
-
-QWidget#lineOSK QLabel#label_header {
-    color: #f0f0f0;
-}
-
-QWidget#lineOSK QLabel#label_sub,
-QWidget#lineOSK QLabel#label_characters,
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich,
-QWidget#boxOSK QLabel#label_characters_box {
-    color: #ccc;
-}
-
-QWidget#buttonsDialog,
-QWidget#buttonsRichDialog,
-QWidget#mainOSK,
-QWidget#headerOSK,
-QWidget#normalOSK,
-QWidget#shiftOSK,
-QWidget#numOSK,
-QWidget#subOSK,
-QWidget#inputOSK,
-QWidget#inputBoxOSK,
-QWidget#charactersOSK,
-QWidget#charactersBoxOSK,
-QWidget#legendOSK,
-QWidget#legendOSK QWidget,
-QWidget#legendOSKshift,
-QWidget#legendOSKshift QWidget,
-QWidget#legendOSKnum,
-QWidget#legendOSKnum QWidget {
-    background: transparent;
-}
-
-QWidget#contentDialog QLabel,
-QWidget#legendOSK QLabel,
-QWidget#legendOSKshift QLabel,
-QWidget#legendOSKnum QLabel {
-    color: rgba(255, 255, 255, 1);
-}
-
-QWidget#contentDialog QLabel#label_dialog {
-    padding: 20px 65px;
-}
-
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich {
-    padding: 0px 65px;
-}
-
-QDialog#OverlayDialog QPushButton {
-    color: rgba(1, 253, 201, 1);
-    background: transparent;
-    border: none;
-    padding: 0px;
-    min-width: 0px;
-}
-
-QDialog#OverlayDialog QPushButton:focus,
-QDialog#OverlayDialog QPushButton:hover {
-    color: rgba(1, 253, 201, 1);
-    background: rgba(58, 61, 66, 1);
-    border: 5px solid rgba(56, 189, 225, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#OverlayDialog QPushButton:pressed {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(150, 150, 150, 1);
-    border: 5px solid rgba(56, 189, 225, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton {
-    color: rgba(255, 255, 255, 1);
-    background: rgba(80, 79, 80, 1);
-    border: 2px solid rgba(71, 69, 71, 1);
-    padding: 0px;
-    min-width: 0px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-    background: rgba(95, 94, 95, 1);
-    border: 2px solid rgba(71, 69, 71, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(255, 255, 255, 1);
-    border: 2px solid rgba(71, 69, 71, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-    color: rgba(0, 0, 0, 1);
-    background: rgba(1, 253, 201, 1);
-    border: 2px solid rgba(71, 69, 71, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
-    color: rgba(255, 255, 255, 1);
-    background: rgba(58, 61, 66, 1);
-    border: 5px solid rgba(56, 189, 225, 1);
-    border-radius: 6px;
-    outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
-    color: rgba(240, 240, 240, 1);
-    background: rgba(150, 150, 150, 1);
-    border: 5px solid rgba(56, 189, 225, 1);
-    border-radius: 6px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_B_dark.png);
-    qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_Y_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-    color: rgba(44, 44, 44, 1);
-    background-position: right top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_plus_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
-    background-position: left top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_shift_lock_off.png);
-    qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
-    background-position: left top;
-    background-repeat: no-repeat;
-    background-origin: content;
-    background-image: url(:/overlay/osk_button_shift_lock_off.png);
-    qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
-    qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
-    padding-bottom: 7px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
-    background: transparent;
-    color: #ccc;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
-    image: url(:/overlay/button_L_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
-    image: url(:/overlay/arrow_left_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
-    image: url(:/overlay/button_R_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
-    image: url(:/overlay/arrow_right_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
-    image: url(:/overlay/button_press_stick_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
-    image: url(:/overlay/button_X_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
-    image: url(:/overlay/button_A_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-    color: rgba(144, 144, 144, 1);
-    background-color: rgba(95, 94, 95, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
-    color: rgba(144, 144, 144, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
-    background-image: url(:/overlay/osk_button_plus_dark_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-    background-image: url(:/overlay/osk_button_B_dark_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
-    background-image: url(:/overlay/osk_button_Y_dark_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QFrame,
-QDialog#QtSoftwareKeyboardDialog QFrame[frameShape="0"],
-QDialog#OverlayDialog QFrame,
-QDialog#OverlayDialog QFrame[frameShape="0"] {
-    border-radius: 0px;
-    border: none;
+/* touchscreen mapping widget */
+TouchScreenPreview {
+    qproperty-dotHighlightColor: #3daee9;
 }
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
index 64e1ecbcc..a64037455 100755
--- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
@@ -1,10 +1,10 @@
 /* ---------------------------------------------------------------------------
 
-  Created by the qtsass compiler v0.1.1
+    Created by the qtsass compiler v0.1.1
 
-  The definitions are in the "qdarkstyle.qss._styles.scss" module
+    The definitions are in the "qdarkstyle.qss._styles.scss" module
 
-  WARNING! All changes made in this file will be lost!
+    WARNING! All changes made in this file will be lost!
 
 --------------------------------------------------------------------------- */
 /* QDarkStyleSheet -----------------------------------------------------------
@@ -15,34 +15,34 @@ It is based on three selecting colors, three greyish (background) colors
 plus three whitish (foreground) colors. Each set of widgets of the same
 type have a header like this:
 
-  ------------------
-  GroupName --------
-  ------------------
+    ------------------
+    GroupName --------
+    ------------------
 
 And each widget is separated with a header like this:
 
-  QWidgetName ------
+    QWidgetName ------
 
 This makes more easy to find and change some css field. The basic
 configuration is described bellow.
 
-  BACKGROUND -----------
+    BACKGROUND -----------
 
-    Light   (unpressed)
-    Normal  (border, disabled, pressed, checked, toolbars, menus)
-    Dark    (background)
+        Light   (unpressed)
+        Normal  (border, disabled, pressed, checked, toolbars, menus)
+        Dark    (background)
 
-  FOREGROUND -----------
+    FOREGROUND -----------
 
-    Light   (texts/labels)
-    Normal  (not used yet)
-    Dark    (disabled texts)
+        Light   (texts/labels)
+        Normal  (not used yet)
+        Dark    (disabled texts)
 
-  SELECTION ------------
+    SELECTION ------------
 
-    Light  (selection/hover/active)
-    Normal (selected)
-    Dark   (selected disabled)
+        Light  (selection/hover/active)
+        Normal (selected)
+        Dark   (selected disabled)
 
 If a stranger configuration is required because of a bugfix or anything
 else, keep the comment on the line above so nobody changes it, including the
@@ -2483,404 +2483,3 @@ QWidget#controllerPlayer7,
 QWidget#controllerPlayer8 {
   background: transparent;
 }
-
-QDialog#QtSoftwareKeyboardDialog,
-QStackedWidget#topOSK {
-  background: rgba(15, 25, 34, .9);
-}
-
-QDialog#OverlayDialog,
-QStackedWidget#stackedDialog {
-  background: rgba(15, 25, 34, .7);
-}
-
-QWidget#boxOSK,
-QWidget#lineOSK,
-QWidget#richDialog,
-QWidget#lineDialog {
-  background: transparent;
-}
-
-QStackedWidget#bottomOSK,
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-  background: rgba(31, 41, 51, 1);
-}
-
-QWidget#contentDialog,
-QWidget#contentRichDialog {
-  margin: 5px;
-  border-radius: 6px;
-}
-
-QWidget#buttonsDialog,
-QWidget#buttonsRichDialog {
-  margin: 5px;
-  border-top: 2px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#legendOSKnum {
-  border-top: 1px solid rgba(255, 255, 255, 1);
-}
-
-QStackedWidget#stackedDialog QTextBrowser QWidget {
-  background: transparent;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar {
-  background: #19232d;
-  border: none;
-}
-
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
-QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
-  border-image: none;
-}
-
-QWidget#mainOSK QStackedWidget,
-QDialog#OverlayDialog QStackedWidget {
-  border: none;
-  padding: 0px;
-}
-
-QWidget#inputOSK {
-  border-bottom: 3px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputOSK QLineEdit {
-  background: transparent;
-  border: none;
-  color: #ccc;
-  padding: 0px;
-}
-
-QWidget#inputBoxOSK {
-  border: 2px solid rgba(255, 255, 255, .9);
-}
-
-QWidget#inputBoxOSK QTextEdit {
-  background: transparent;
-  border: none;
-  color: #ccc;
-}
-
-QWidget#richDialog QTextBrowser {
-  background: transparent;
-  border: none;
-  color: #fff;
-  padding: 35px 65px;
-}
-
-QWidget#lineOSK QLabel#label_header {
-  color: #f0f0f0;
-}
-
-QWidget#lineOSK QLabel#label_sub,
-QWidget#lineOSK QLabel#label_characters,
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich,
-QWidget#boxOSK QLabel#label_characters_box {
-  color: #ccc;
-}
-
-QWidget#buttonsDialog,
-QWidget#buttonsRichDialog,
-QWidget#mainOSK,
-QWidget#headerOSK,
-QWidget#normalOSK,
-QWidget#shiftOSK,
-QWidget#numOSK,
-QWidget#subOSK,
-QWidget#inputOSK,
-QWidget#inputBoxOSK,
-QWidget#charactersOSK,
-QWidget#charactersBoxOSK,
-QWidget#legendOSK,
-QWidget#legendOSK QWidget,
-QWidget#legendOSKshift,
-QWidget#legendOSKshift QWidget,
-QWidget#legendOSKnum,
-QWidget#legendOSKnum QWidget {
-  background: transparent;
-}
-
-QWidget#contentDialog QLabel,
-QWidget#legendOSK QLabel,
-QWidget#legendOSKshift QLabel,
-QWidget#legendOSKnum QLabel {
-  color: rgba(255, 255, 255, 1);
-}
-
-QWidget#contentDialog QLabel#label_dialog {
-  padding: 20px 65px;
-}
-
-QWidget#contentDialog QLabel#label_title,
-QWidget#contentRichDialog QLabel#label_title_rich {
-  padding: 0px 65px;
-}
-
-QDialog#OverlayDialog QPushButton {
-  color: rgba(1, 253, 201, 1);
-  background: transparent;
-  border: none;
-  padding: 0px;
-  min-width: 0px;
-}
-
-QDialog#OverlayDialog QPushButton:focus,
-QDialog#OverlayDialog QPushButton:hover {
-  color: rgba(1, 253, 201, 1);
-  background: rgba(18, 33, 46, 1);
-  border: 5px solid rgba(56, 189, 225, 1);
-  border-radius: 6px;
-  outline: none;
-}
-
-QDialog#OverlayDialog QPushButton:pressed {
-  color: rgba(240, 240, 240, 1);
-  background: rgba(110, 122, 130, 1);
-  border: 5px solid rgba(56, 189, 225, 1);
-  border-radius: 6px;
-  outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QLabel {
-  padding: 0px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton {
-  color: rgba(255, 255, 255, 1);
-  background: rgba(40, 51, 60, 1);
-  border: 2px solid rgba(31, 41, 51, 1);
-  border-radius: 0px;
-  padding: 0px;
-  min-width: 0px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-  background: rgba(55, 66, 75, 1);
-  border: 2px solid rgba(31, 41, 51, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-  color: rgba(240, 240, 240, 1);
-  background: rgba(255, 255, 255, 1);
-  border: 2px solid rgba(31, 41, 51, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-  color: rgba(0, 0, 0, 1);
-  background: rgba(1, 253, 201, 1);
-  border: 2px solid rgba(31, 41, 51, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
-  color: rgba(255, 255, 255, 1);
-  background: rgba(18, 33, 46, 1);
-  border: 5px solid rgba(56, 189, 225, 1);
-  border-radius: 6px;
-  outline: none;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
-  color: rgba(240, 240, 240, 1);
-  background: rgba(110, 122, 130, 1);
-  border: 5px solid rgba(56, 189, 225, 1);
-  border-radius: 6px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
-  background-position: right top;
-  background-repeat: no-repeat;
-  background-origin: content;
-  background-image: url(:/overlay/osk_button_B_dark.png);
-  qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
-  qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
-  background-position: right top;
-  background-repeat: no-repeat;
-  background-origin: content;
-  background-image: url(:/overlay/osk_button_Y_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
-  color: rgba(44, 44, 44, 1);
-  background-position: right top;
-  background-repeat: no-repeat;
-  background-origin: content;
-  background-image: url(:/overlay/osk_button_plus_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
-  background-position: left top;
-  background-repeat: no-repeat;
-  background-origin: content;
-  background-image: url(:/overlay/osk_button_shift_lock_off.png);
-  qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
-  qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
-  background-position: left top;
-  background-repeat: no-repeat;
-  background-origin: content;
-  background-image: url(:/overlay/osk_button_shift_lock_off.png);
-  qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
-  qproperty-iconSize: 36px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
-  padding-bottom: 7px;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
-  background: transparent;
-  color: #ccc;
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
-  image: url(:/overlay/button_L_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
-  image: url(:/overlay/arrow_left_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
-  image: url(:/overlay/button_R_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
-  image: url(:/overlay/arrow_right_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
-  image: url(:/overlay/button_press_stick_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
-  image: url(:/overlay/button_X_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
-QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
-  image: url(:/overlay/button_A_dark.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-  color: rgba(144, 144, 144, 1);
-  background-color: rgba(55, 66, 75, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
-  color: rgba(144, 144, 144, 1);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
-  background-image: url(:/overlay/osk_button_plus_dark_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
-  background-image: url(:/overlay/osk_button_B_dark_disabled.png);
-}
-
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
-QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
-  background-image: url(:/overlay/osk_button_Y_dark_disabled.png);
-}
diff --git a/dist/yuzu.ico b/dist/yuzu.ico
index 7c998a5c53a3b079b67c526586c269f2efd25447..df3be8464fcb3c0fb10308472ed527dbcdc10d61 100755
GIT binary patch
literal 23159
zcmd6v2|ShA|HmJ@Q1&$;YY0U}$yUUzWKY=>QDg~Gk}KH@U1?Q>qzx@1RM(cFMJOt=
zwh&p0?Dzh^$K2ch)-==1H1qrY?!4afJ<oHN@8>MfdCobHR~SZzF=FUPhe=?2#4&6Q
zgcmLP^*UPy!|uU72?@$I7lyeRU>Fxzl-?b(a&E-17}E`gv)M%0AnR<Lk-j;KMX)l1
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

literal 25355
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

diff --git a/dist/yuzu.svg b/dist/yuzu.svg
index 98ded2d8f..93171d1bf 100755
--- a/dist/yuzu.svg
+++ b/dist/yuzu.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612.15 680.17"><defs><style>.cls-1{fill:#c6c6c6;}.cls-2{fill:#ffdc00;}</style></defs><title>newAsset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="g823"><g id="right"><g id="g827"><g id="g833"><path id="path835" class="cls-1" d="M340.08,136V680.17c150.26,0,272.07-121.81,272.07-272.07S490.34,136,340.08,136m53.14,59.6a219.06,219.06,0,0,1,0,424.94V195.63"/></g></g></g><g id="left"><g id="g839"><g id="g845"><path id="path847" class="cls-2" d="M272.07,0C121.81,0,0,121.81,0,272.07S121.81,544.13,272.07,544.13ZM218.93,59.6V484.54A219,219,0,0,1,117.26,117.26,217.44,217.44,0,0,1,218.93,59.6"/></g></g></g></g></g></g></svg>
\ No newline at end of file
+<svg id="svg815" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 614.4 682.67"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#ff3c28;}.cls-4{fill:#0ab9e6;}</style><clipPath id="clip-path"><rect class="cls-1" x="-43" y="-46.67" width="699.6" height="777.33"/></clipPath></defs><title>Artboard 1</title><g id="g823"><g id="right"><g class="cls-2"><g id="g827"><g id="g833"><path id="path835" class="cls-3" d="M340.81,138V682.08c150.26,0,272.06-121.81,272.06-272.06S491.07,138,340.81,138M394,197.55a219.06,219.06,0,0,1,0,424.94V197.55"/></g></g></g></g><g id="left"><g class="cls-2"><g id="g839"><g id="g845"><path id="path847" class="cls-4" d="M272.79,1.92C122.53,1.92.73,123.73.73,274s121.8,272.07,272.06,272.07ZM219.65,61.51v425A219,219,0,0,1,118,119.18,217.51,217.51,0,0,1,219.65,61.51"/></g></g></g></g></g></svg>
\ No newline at end of file
diff --git a/src/common/assert.cpp b/src/common/assert.cpp
index c3b70797d..d7d91b96b 100755
--- a/src/common/assert.cpp
+++ b/src/common/assert.cpp
@@ -4,4 +4,8 @@
 
 #include "common/assert.h"
 
-void assert_handle_failure() {}
+#include "common/common_funcs.h"
+
+void assert_handle_failure() {
+    Crash();
+}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7d9eba928..167ee13f3 100755
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -273,7 +273,6 @@ add_library(core STATIC
     hle/service/am/applets/profile_select.h
     hle/service/am/applets/software_keyboard.cpp
     hle/service/am/applets/software_keyboard.h
-    hle/service/am/applets/software_keyboard_types.h
     hle/service/am/applets/web_browser.cpp
     hle/service/am/applets/web_browser.h
     hle/service/am/applets/web_types.h
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index 12c76c9ee..856ed33da 100755
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -1,149 +1,29 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu emulator team
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <thread>
-
-#include "common/logging/log.h"
+#include "common/logging/backend.h"
 #include "common/string_util.h"
 #include "core/frontend/applets/software_keyboard.h"
 
 namespace Core::Frontend {
-
 SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
 
-DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
+void DefaultSoftwareKeyboardApplet::RequestText(
+    std::function<void(std::optional<std::u16string>)> out,
+    SoftwareKeyboardParameters parameters) const {
+    if (parameters.initial_text.empty())
+        out(u"yuzu");
 
-void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
-    bool is_inline, KeyboardInitializeParameters initialize_parameters,
-    std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
-    std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-        submit_inline_callback_) {
-    if (is_inline) {
-        LOG_WARNING(
-            Service_AM,
-            "(STUBBED) called, backend requested to initialize the inline software keyboard.");
-
-        submit_inline_callback = std::move(submit_inline_callback_);
-    } else {
-        LOG_WARNING(
-            Service_AM,
-            "(STUBBED) called, backend requested to initialize the normal software keyboard.");
-
-        submit_normal_callback = std::move(submit_normal_callback_);
-    }
-
-    parameters = std::move(initialize_parameters);
-
-    LOG_INFO(Service_AM,
-             "\nKeyboardInitializeParameters:"
-             "\nok_text={}"
-             "\nheader_text={}"
-             "\nsub_text={}"
-             "\nguide_text={}"
-             "\ninitial_text={}"
-             "\nmax_text_length={}"
-             "\nmin_text_length={}"
-             "\ninitial_cursor_position={}"
-             "\ntype={}"
-             "\npassword_mode={}"
-             "\ntext_draw_type={}"
-             "\nkey_disable_flags={}"
-             "\nuse_blur_background={}"
-             "\nenable_backspace_button={}"
-             "\nenable_return_button={}"
-             "\ndisable_cancel_button={}",
-             Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text),
-             Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text),
-             Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length,
-             parameters.min_text_length, parameters.initial_cursor_position, parameters.type,
-             parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw,
-             parameters.use_blur_background, parameters.enable_backspace_button,
-             parameters.enable_return_button, parameters.disable_cancel_button);
+    out(parameters.initial_text);
 }
 
-void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
+void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(
+    std::u16string error_message, std::function<void()> finished_check) const {
     LOG_WARNING(Service_AM,
-                "(STUBBED) called, backend requested to show the normal software keyboard.");
-
-    SubmitNormalText(u"yuzu");
+                "(STUBBED) called - Default fallback software keyboard does not support text "
+                "check! (error_message={})",
+                Common::UTF16ToUTF8(error_message));
+    finished_check();
 }
-
-void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
-    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-    std::u16string text_check_message) const {
-    LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog.");
-}
-
-void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard(
-    InlineAppearParameters appear_parameters) const {
-    LOG_WARNING(Service_AM,
-                "(STUBBED) called, backend requested to show the inline software keyboard.");
-
-    LOG_INFO(Service_AM,
-             "\nInlineAppearParameters:"
-             "\nmax_text_length={}"
-             "\nmin_text_length={}"
-             "\nkey_top_scale_x={}"
-             "\nkey_top_scale_y={}"
-             "\nkey_top_translate_x={}"
-             "\nkey_top_translate_y={}"
-             "\ntype={}"
-             "\nkey_disable_flags={}"
-             "\nkey_top_as_floating={}"
-             "\nenable_backspace_button={}"
-             "\nenable_return_button={}"
-             "\ndisable_cancel_button={}",
-             appear_parameters.max_text_length, appear_parameters.min_text_length,
-             appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
-             appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
-             appear_parameters.type, appear_parameters.key_disable_flags.raw,
-             appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
-             appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
-
-    std::thread([this] { SubmitInlineText(u"yuzu"); }).detach();
-}
-
-void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
-    LOG_WARNING(Service_AM,
-                "(STUBBED) called, backend requested to hide the inline software keyboard.");
-}
-
-void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const {
-    LOG_WARNING(Service_AM,
-                "(STUBBED) called, backend requested to change the inline keyboard text.");
-
-    LOG_INFO(Service_AM,
-             "\nInlineTextParameters:"
-             "\ninput_text={}"
-             "\ncursor_position={}",
-             Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
-
-    submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
-                           text_parameters.input_text, text_parameters.cursor_position);
-}
-
-void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
-    LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard.");
-}
-
-void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
-    submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text);
-}
-
-void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
-    std::this_thread::sleep_for(std::chrono::milliseconds(500));
-
-    for (std::size_t index = 0; index < text.size(); ++index) {
-        submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
-                               std::u16string(text.data(), text.data() + index + 1),
-                               static_cast<s32>(index) + 1);
-
-        std::this_thread::sleep_for(std::chrono::milliseconds(250));
-    }
-
-    submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text),
-                           static_cast<s32>(text.size()));
-}
-
 } // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index 506eb35bb..f9b202664 100755
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -1,116 +1,54 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu emulator team
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
 #pragma once
 
 #include <functional>
-#include <thread>
-
+#include <optional>
+#include <string>
+#include "common/bit_field.h"
 #include "common/common_types.h"
 
-#include "core/hle/service/am/applets/software_keyboard_types.h"
-
 namespace Core::Frontend {
-
-struct KeyboardInitializeParameters {
-    std::u16string ok_text;
+struct SoftwareKeyboardParameters {
+    std::u16string submit_text;
     std::u16string header_text;
     std::u16string sub_text;
     std::u16string guide_text;
     std::u16string initial_text;
-    u32 max_text_length;
-    u32 min_text_length;
-    s32 initial_cursor_position;
-    Service::AM::Applets::SwkbdType type;
-    Service::AM::Applets::SwkbdPasswordMode password_mode;
-    Service::AM::Applets::SwkbdTextDrawType text_draw_type;
-    Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
-    bool use_blur_background;
-    bool enable_backspace_button;
-    bool enable_return_button;
-    bool disable_cancel_button;
-};
+    std::size_t max_length;
+    bool password;
+    bool cursor_at_beginning;
 
-struct InlineAppearParameters {
-    u32 max_text_length;
-    u32 min_text_length;
-    f32 key_top_scale_x;
-    f32 key_top_scale_y;
-    f32 key_top_translate_x;
-    f32 key_top_translate_y;
-    Service::AM::Applets::SwkbdType type;
-    Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
-    bool key_top_as_floating;
-    bool enable_backspace_button;
-    bool enable_return_button;
-    bool disable_cancel_button;
-};
+    union {
+        u8 value;
 
-struct InlineTextParameters {
-    std::u16string input_text;
-    s32 cursor_position;
+        BitField<1, 1, u8> disable_space;
+        BitField<2, 1, u8> disable_address;
+        BitField<3, 1, u8> disable_percent;
+        BitField<4, 1, u8> disable_slash;
+        BitField<6, 1, u8> disable_number;
+        BitField<7, 1, u8> disable_download_code;
+    };
 };
 
 class SoftwareKeyboardApplet {
 public:
     virtual ~SoftwareKeyboardApplet();
 
-    virtual void InitializeKeyboard(
-        bool is_inline, KeyboardInitializeParameters initialize_parameters,
-        std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
-            submit_normal_callback_,
-        std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-            submit_inline_callback_) = 0;
-
-    virtual void ShowNormalKeyboard() const = 0;
-
-    virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                                     std::u16string text_check_message) const = 0;
-
-    virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0;
-
-    virtual void HideInlineKeyboard() const = 0;
-
-    virtual void InlineTextChanged(InlineTextParameters text_parameters) const = 0;
-
-    virtual void ExitKeyboard() const = 0;
+    virtual void RequestText(std::function<void(std::optional<std::u16string>)> out,
+                             SoftwareKeyboardParameters parameters) const = 0;
+    virtual void SendTextCheckDialog(std::u16string error_message,
+                                     std::function<void()> finished_check) const = 0;
 };
 
 class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
 public:
-    ~DefaultSoftwareKeyboardApplet() override;
-
-    void InitializeKeyboard(
-        bool is_inline, KeyboardInitializeParameters initialize_parameters,
-        std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
-            submit_normal_callback_,
-        std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-            submit_inline_callback_) override;
-
-    void ShowNormalKeyboard() const override;
-
-    void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                             std::u16string text_check_message) const override;
-
-    void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override;
-
-    void HideInlineKeyboard() const override;
-
-    void InlineTextChanged(InlineTextParameters text_parameters) const override;
-
-    void ExitKeyboard() const override;
-
-private:
-    void SubmitNormalText(std::u16string text) const;
-    void SubmitInlineText(std::u16string_view text) const;
-
-    KeyboardInitializeParameters parameters;
-
-    mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
-        submit_normal_callback;
-    mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-        submit_inline_callback;
+    void RequestText(std::function<void(std::optional<std::u16string>)> out,
+                     SoftwareKeyboardParameters parameters) const override;
+    void SendTextCheckDialog(std::u16string error_message,
+                             std::function<void()> finished_check) const override;
 };
 
 } // namespace Core::Frontend
diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp
index 9f6a90e8f..ec5fe660e 100755
--- a/src/core/frontend/input_interpreter.cpp
+++ b/src/core/frontend/input_interpreter.cpp
@@ -12,9 +12,7 @@ InputInterpreter::InputInterpreter(Core::System& system)
     : npad{system.ServiceManager()
                .GetService<Service::HID::Hid>("hid")
                ->GetAppletResource()
-               ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
-    ResetButtonStates();
-}
+               ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {}
 
 InputInterpreter::~InputInterpreter() = default;
 
@@ -27,17 +25,6 @@ void InputInterpreter::PollInput() {
     button_states[current_index] = button_state;
 }
 
-void InputInterpreter::ResetButtonStates() {
-    previous_index = 0;
-    current_index = 0;
-
-    button_states[0] = 0xFFFFFFFF;
-
-    for (std::size_t i = 1; i < button_states.size(); ++i) {
-        button_states[i] = 0;
-    }
-}
-
 bool InputInterpreter::IsButtonPressed(HIDButton button) const {
     return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0;
 }
diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h
index 9495e3daf..73fc47ffb 100755
--- a/src/core/frontend/input_interpreter.h
+++ b/src/core/frontend/input_interpreter.h
@@ -66,9 +66,6 @@ public:
     /// Gets a button state from HID and inserts it into the array of button states.
     void PollInput();
 
-    /// Resets all the button states to their defaults.
-    void ResetButtonStates();
-
     /**
      * Checks whether the button is pressed.
      *
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 2b363b1d9..161d9f782 100755
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -75,14 +75,10 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
         if (incoming) {
             // Populate the object lists with the data in the IPC request.
             for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
-                const u32 copy_handle{rp.Pop<Handle>()};
-                copy_handles.push_back(copy_handle);
-                copy_objects.push_back(handle_table.GetGeneric(copy_handle));
+                copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
             }
             for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
-                const u32 move_handle{rp.Pop<Handle>()};
-                move_handles.push_back(move_handle);
-                move_objects.push_back(handle_table.GetGeneric(move_handle));
+                move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
             }
         } else {
             // For responses we just ignore the handles, they're empty and will be populated when
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 6fba42615..9a769781b 100755
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -210,14 +210,6 @@ public:
     /// Helper function to test whether the output buffer at buffer_index can be written
     bool CanWriteBuffer(std::size_t buffer_index = 0) const;
 
-    Handle GetCopyHandle(std::size_t index) const {
-        return copy_handles.at(index);
-    }
-
-    Handle GetMoveHandle(std::size_t index) const {
-        return move_handles.at(index);
-    }
-
     template <typename T>
     std::shared_ptr<T> GetCopyObject(std::size_t index) {
         return DynamicObjectCast<T>(copy_objects.at(index));
@@ -293,8 +285,6 @@ private:
     std::shared_ptr<Kernel::ServerSession> server_session;
     std::shared_ptr<KThread> thread;
     // TODO(yuriks): Check common usage of this and optimize size accordingly
-    boost::container::small_vector<Handle, 8> move_handles;
-    boost::container::small_vector<Handle, 8> copy_handles;
     boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects;
     boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects;
     boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 1c86fdd20..b442dfe57 100755
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -402,7 +402,7 @@ public:
         return wait_cancelled;
     }
 
-    [[nodiscard]] void ClearWaitCancelled() {
+    void ClearWaitCancelled() {
         wait_cancelled = false;
     }
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f7d3f218a..8fd990577 100755
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -67,13 +67,8 @@ struct KernelCore::Impl {
         is_phantom_mode_for_singlecore = false;
 
         InitializePhysicalCores();
-
-        // Derive the initial memory layout from the emulated board
-        KMemoryLayout memory_layout;
-        DeriveInitialMemoryLayout(memory_layout);
-        InitializeMemoryLayout(memory_layout);
-        InitializeSystemResourceLimit(kernel, system, memory_layout);
-        InitializeSlabHeaps();
+        InitializeSystemResourceLimit(kernel, system);
+        InitializeMemoryLayout();
         InitializeSchedulers();
         InitializeSuspendThreads();
         InitializePreemption(kernel);
@@ -142,32 +137,27 @@ struct KernelCore::Impl {
     }
 
     // Creates the default system resource limit
-    void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system,
-                                       const KMemoryLayout& memory_layout) {
+    void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
         system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
-        const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
 
         // If setting the default system values fails, then something seriously wrong has occurred.
-        ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
+        ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
                    .IsSuccess());
         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
                    .IsSuccess());
         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
-        system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
 
+        // Derived from recent software updates. The kernel reserves 27MB
+        constexpr u64 kernel_size{0x1b00000};
+        if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
+            UNREACHABLE();
+        }
         // Reserve secure applet memory, introduced in firmware 5.0.0
-        constexpr u64 secure_applet_memory_size{Common::Size_4_MB};
+        constexpr u64 secure_applet_memory_size{0x400000};
         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
                                               secure_applet_memory_size));
-
-        // This memory seems to be reserved on hardware, but is not reserved/used by yuzu.
-        // Likely Horizon OS reserved memory
-        // TODO(ameerj): Derive the memory rather than hardcode it.
-        constexpr u64 unknown_reserved_memory{0x2f896000};
-        ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
-                                              unknown_reserved_memory));
     }
 
     void InitializePreemption(KernelCore& kernel) {
@@ -541,7 +531,11 @@ struct KernelCore::Impl {
                                                         linear_region_start);
     }
 
-    void InitializeMemoryLayout(const KMemoryLayout& memory_layout) {
+    void InitializeMemoryLayout() {
+        // Derive the initial memory layout from the emulated board
+        KMemoryLayout memory_layout;
+        DeriveInitialMemoryLayout(memory_layout);
+
         const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
         const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
         const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
@@ -584,14 +578,11 @@ struct KernelCore::Impl {
             system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
             KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
             "Time:SharedMemory");
-    }
 
-    void InitializeSlabHeaps() {
         // Allocate slab heaps
         user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
 
-        // TODO(ameerj): This should be derived, not hardcoded within the kernel
-        constexpr u64 user_slab_heap_size{0x3de000};
+        constexpr u64 user_slab_heap_size{0x1ef000};
         // Reserve slab heaps
         ASSERT(
             system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 51a9c393b..9d5956ead 100755
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -120,7 +120,9 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
     std::shared_ptr<Process> process = std::make_shared<Process>(system);
     process->name = std::move(name);
 
-    process->resource_limit = kernel.GetSystemResourceLimit();
+    // TODO: This is inaccurate
+    // The process should hold a reference to the kernel-wide resource limit.
+    process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
     process->status = ProcessStatus::Created;
     process->program_id = 0;
     process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -158,6 +160,9 @@ void Process::DecrementThreadCount() {
 }
 
 u64 Process::GetTotalPhysicalMemoryAvailable() const {
+    // TODO: This is expected to always return the application memory pool size after accurately
+    // reserving kernel resources. The current workaround uses a process-local resource limit of
+    // application memory pool size, which is inaccurate.
     const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
                        page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
                        main_thread_stack_size};
@@ -165,6 +170,7 @@ u64 Process::GetTotalPhysicalMemoryAvailable() const {
     if (capacity < memory_usage_capacity) {
         return capacity;
     }
+
     return memory_usage_capacity;
 }
 
@@ -266,6 +272,10 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
     system_resource_size = metadata.GetSystemResourceSize();
     image_size = code_size;
 
+    // Set initial resource limits
+    resource_limit->SetLimitValue(
+        LimitableResource::PhysicalMemory,
+        kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
     KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
                                                   code_size + system_resource_size);
     if (!memory_reservation.Succeeded()) {
@@ -314,6 +324,16 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
         UNREACHABLE();
     }
 
+    // Set initial resource limits
+    resource_limit->SetLimitValue(
+        LimitableResource::PhysicalMemory,
+        kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
+
+    resource_limit->SetLimitValue(LimitableResource::Threads, 608);
+    resource_limit->SetLimitValue(LimitableResource::Events, 700);
+    resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
+    resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
+
     // Create TLS region
     tls_region_address = CreateTLSRegion();
     memory_reservation.Commit();
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index b5cef7f9f..4374487a3 100755
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -971,7 +971,7 @@ private:
 
         auto storage = applet->GetBroker().PopNormalDataToGame();
         if (storage == nullptr) {
-            LOG_DEBUG(Service_AM,
+            LOG_ERROR(Service_AM,
                       "storage is a nullptr. There is no data in the current normal channel");
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -1002,7 +1002,7 @@ private:
 
         auto storage = applet->GetBroker().PopInteractiveDataToGame();
         if (storage == nullptr) {
-            LOG_DEBUG(Service_AM,
+            LOG_ERROR(Service_AM,
                       "storage is a nullptr. There is no data in the current interactive channel");
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -1125,7 +1125,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
         {2, nullptr, "AreAnyLibraryAppletsLeft"},
         {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
         {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
-        {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
+        {12, nullptr, "CreateHandleStorage"},
     };
     RegisterHandlers(functions);
 }
@@ -1134,15 +1134,14 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
 
 void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-
     const auto applet_id = rp.PopRaw<Applets::AppletId>();
-    const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
+    const auto applet_mode = rp.PopRaw<u32>();
 
     LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
               applet_mode);
 
     const auto& applet_manager{system.GetAppletManager()};
-    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
+    const auto applet = applet_manager.GetApplet(applet_id);
 
     if (applet == nullptr) {
         LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
@@ -1160,18 +1159,9 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
 
 void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-
-    const s64 size{rp.Pop<s64>()};
-
+    const u64 size{rp.Pop<u64>()};
     LOG_DEBUG(Service_AM, "called, size={}", size);
 
-    if (size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_UNKNOWN);
-        return;
-    }
-
     std::vector<u8> buffer(size);
 
     IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -1180,65 +1170,18 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
 }
 
 void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
     IPC::RequestParser rp{ctx};
 
-    struct Parameters {
-        u8 permissions;
-        s64 size;
-    };
-
-    const auto parameters{rp.PopRaw<Parameters>()};
-    const auto handle{ctx.GetCopyHandle(0)};
-
-    LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
-              parameters.size, handle);
-
-    if (parameters.size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_UNKNOWN);
-        return;
-    }
+    rp.SetCurrentOffset(3);
+    const auto handle{rp.Pop<Kernel::Handle>()};
 
     auto transfer_mem =
         system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
 
     if (transfer_mem == nullptr) {
-        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_UNKNOWN);
-        return;
-    }
-
-    const u8* const mem_begin = transfer_mem->GetPointer();
-    const u8* const mem_end = mem_begin + transfer_mem->GetSize();
-    std::vector<u8> memory{mem_begin, mem_end};
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(RESULT_SUCCESS);
-    rb.PushIpcInterface<IStorage>(system, std::move(memory));
-}
-
-void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const s64 size{rp.Pop<s64>()};
-    const auto handle{ctx.GetCopyHandle(0)};
-
-    LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
-
-    if (size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_UNKNOWN);
-        return;
-    }
-
-    auto transfer_mem =
-        system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
-
-    if (transfer_mem == nullptr) {
-        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
+        LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_UNKNOWN);
         return;
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index aefbdf0d5..f6a453ab7 100755
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -254,7 +254,6 @@ private:
     void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
     void CreateStorage(Kernel::HLERequestContext& ctx);
     void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx);
-    void CreateHandleStorage(Kernel::HLERequestContext& ctx);
 };
 
 class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 5ddad851a..e2f3b7563 100755
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -241,31 +241,31 @@ void AppletManager::ClearAll() {
     frontend = {};
 }
 
-std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
+std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
     switch (id) {
     case AppletId::Auth:
-        return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
+        return std::make_shared<Auth>(system, *frontend.parental_controls);
     case AppletId::Controller:
-        return std::make_shared<Controller>(system, mode, *frontend.controller);
+        return std::make_shared<Controller>(system, *frontend.controller);
     case AppletId::Error:
-        return std::make_shared<Error>(system, mode, *frontend.error);
+        return std::make_shared<Error>(system, *frontend.error);
     case AppletId::ProfileSelect:
-        return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
+        return std::make_shared<ProfileSelect>(system, *frontend.profile_select);
     case AppletId::SoftwareKeyboard:
-        return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
+        return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard);
     case AppletId::Web:
     case AppletId::Shop:
     case AppletId::OfflineWeb:
     case AppletId::LoginShare:
     case AppletId::WebAuth:
-        return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
+        return std::make_shared<WebBrowser>(system, *frontend.web_browser);
     case AppletId::PhotoViewer:
-        return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
+        return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer);
     default:
         UNIMPLEMENTED_MSG(
             "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
             static_cast<u8>(id));
-        return std::make_shared<StubApplet>(system, id, mode);
+        return std::make_shared<StubApplet>(system, id);
     }
 }
 
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 26b482015..b9a006317 100755
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -62,14 +62,6 @@ enum class AppletId : u32 {
     MyPage = 0x1A,
 };
 
-enum class LibraryAppletMode : u32 {
-    AllForeground = 0,
-    Background = 1,
-    NoUI = 2,
-    BackgroundIndirectDisplay = 3,
-    AllForegroundInitiallyHidden = 4,
-};
-
 class AppletDataBroker final {
 public:
     explicit AppletDataBroker(Kernel::KernelCore& kernel_);
@@ -208,7 +200,7 @@ public:
     void SetDefaultAppletsIfMissing();
     void ClearAll();
 
-    std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
+    std::shared_ptr<Applet> GetApplet(AppletId id) const;
 
 private:
     AppletFrontendSet frontend;
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp
index a33f05f97..c2bfe698f 100755
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -45,9 +45,8 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
     };
 }
 
-Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
-                       const Core::Frontend::ControllerApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 Controller::~Controller() = default;
 
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h
index 07cb92bf9..d4c9da7b1 100755
--- a/src/core/hle/service/am/applets/controller.h
+++ b/src/core/hle/service/am/applets/controller.h
@@ -106,8 +106,7 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
 
 class Controller final : public Applet {
 public:
-    explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_,
-                        const Core::Frontend::ControllerApplet& frontend_);
+    explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_);
     ~Controller() override;
 
     void Initialize() override;
@@ -120,7 +119,6 @@ public:
     void ConfigurationComplete();
 
 private:
-    LibraryAppletMode applet_mode;
     const Core::Frontend::ControllerApplet& frontend;
     Core::System& system;
 
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index a9f0a9c95..0c8b632e8 100755
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -86,9 +86,8 @@ ResultCode Decode64BitError(u64 error) {
 
 } // Anonymous namespace
 
-Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
-             const Core::Frontend::ErrorApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 Error::~Error() = default;
 
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
index a3e520cd4..a105cdb0c 100755
--- a/src/core/hle/service/am/applets/error.h
+++ b/src/core/hle/service/am/applets/error.h
@@ -25,8 +25,7 @@ enum class ErrorAppletMode : u8 {
 
 class Error final : public Applet {
 public:
-    explicit Error(Core::System& system_, LibraryAppletMode applet_mode_,
-                   const Core::Frontend::ErrorApplet& frontend_);
+    explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_);
     ~Error() override;
 
     void Initialize() override;
@@ -41,7 +40,6 @@ public:
 private:
     union ErrorArguments;
 
-    LibraryAppletMode applet_mode;
     const Core::Frontend::ErrorApplet& frontend;
     ResultCode error_code = RESULT_SUCCESS;
     ErrorAppletMode mode = ErrorAppletMode::ShowError;
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 71016cce7..4d1df5cbe 100755
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -37,9 +37,8 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
     }
 }
 
-Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
-           Core::Frontend::ParentalControlsApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 Auth::~Auth() = default;
 
@@ -153,9 +152,8 @@ void Auth::AuthFinished(bool is_successful) {
     broker.SignalStateChanged();
 }
 
-PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
-                         const Core::Frontend::PhotoViewerApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 PhotoViewer::~PhotoViewer() = default;
 
@@ -204,8 +202,8 @@ void PhotoViewer::ViewFinished() {
     broker.SignalStateChanged();
 }
 
-StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
-    : Applet{system_.Kernel()}, id{id_}, applet_mode{applet_mode_}, system{system_} {}
+StubApplet::StubApplet(Core::System& system_, AppletId id_)
+    : Applet{system_.Kernel()}, id{id_}, system{system_} {}
 
 StubApplet::~StubApplet() = default;
 
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
index d9e6d4384..ba76ae3d3 100755
--- a/src/core/hle/service/am/applets/general_backend.h
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -20,8 +20,7 @@ enum class AuthAppletType : u32 {
 
 class Auth final : public Applet {
 public:
-    explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
-                  Core::Frontend::ParentalControlsApplet& frontend_);
+    explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_);
     ~Auth() override;
 
     void Initialize() override;
@@ -33,7 +32,6 @@ public:
     void AuthFinished(bool is_successful = true);
 
 private:
-    LibraryAppletMode applet_mode;
     Core::Frontend::ParentalControlsApplet& frontend;
     Core::System& system;
     bool complete = false;
@@ -52,8 +50,7 @@ enum class PhotoViewerAppletMode : u8 {
 
 class PhotoViewer final : public Applet {
 public:
-    explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
-                         const Core::Frontend::PhotoViewerApplet& frontend_);
+    explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_);
     ~PhotoViewer() override;
 
     void Initialize() override;
@@ -65,7 +62,6 @@ public:
     void ViewFinished();
 
 private:
-    LibraryAppletMode applet_mode;
     const Core::Frontend::PhotoViewerApplet& frontend;
     bool complete = false;
     PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
@@ -74,7 +70,7 @@ private:
 
 class StubApplet final : public Applet {
 public:
-    explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
+    explicit StubApplet(Core::System& system_, AppletId id_);
     ~StubApplet() override;
 
     void Initialize() override;
@@ -86,7 +82,6 @@ public:
 
 private:
     AppletId id;
-    LibraryAppletMode applet_mode;
     Core::System& system;
 };
 
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index ab8b6fcc5..77fba16c7 100755
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,9 +15,9 @@ namespace Service::AM::Applets {
 
 constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
 
-ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
+ProfileSelect::ProfileSelect(Core::System& system_,
                              const Core::Frontend::ProfileSelectApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 ProfileSelect::~ProfileSelect() = default;
 
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 90f054030..648d33a24 100755
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
 
 class ProfileSelect final : public Applet {
 public:
-    explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
+    explicit ProfileSelect(Core::System& system_,
                            const Core::Frontend::ProfileSelectApplet& frontend_);
     ~ProfileSelect() override;
 
@@ -47,7 +47,6 @@ public:
     void SelectionComplete(std::optional<Common::UUID> uuid);
 
 private:
-    LibraryAppletMode applet_mode;
     const Core::Frontend::ProfileSelectApplet& frontend;
 
     UserSelectionConfig config;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index c3a05de9c..79b209c6b 100755
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -1,80 +1,93 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu emulator team
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <cstring>
+#include "common/assert.h"
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/frontend/applets/software_keyboard.h"
+#include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/software_keyboard.h"
 
 namespace Service::AM::Applets {
 
 namespace {
-
-// The maximum number of UTF-16 characters that can be input into the swkbd text field.
-constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500;
-
-constexpr std::size_t REPLY_BASE_SIZE = sizeof(SwkbdState) + sizeof(SwkbdReplyType);
-constexpr std::size_t REPLY_UTF8_SIZE = 0x7D4;
-constexpr std::size_t REPLY_UTF16_SIZE = 0x3EC;
-
-constexpr const char* GetTextCheckResultName(SwkbdTextCheckResult text_check_result) {
-    switch (text_check_result) {
-    case SwkbdTextCheckResult::Success:
-        return "Success";
-    case SwkbdTextCheckResult::Failure:
-        return "Failure";
-    case SwkbdTextCheckResult::Confirm:
-        return "Confirm";
-    case SwkbdTextCheckResult::Silent:
-        return "Silent";
-    default:
-        UNIMPLEMENTED_MSG("Unknown TextCheckResult={}", text_check_result);
-        return "Unknown";
-    }
-}
-
-void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply_type) {
-    std::memcpy(reply.data(), &state, sizeof(SwkbdState));
-    std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType));
-}
-
+enum class Request : u32 {
+    Finalize = 0x4,
+    SetUserWordInfo = 0x6,
+    SetCustomizeDic = 0x7,
+    Calc = 0xa,
+    SetCustomizedDictionaries = 0xb,
+    UnsetCustomizedDictionaries = 0xc,
+    UnknownD = 0xd,
+    UnknownE = 0xe,
+};
+constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8;
+constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8;
+constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4;
+constexpr std::size_t DEFAULT_MAX_LENGTH = 500;
+constexpr bool INTERACTIVE_STATUS_OK = false;
 } // Anonymous namespace
+static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
+    KeyboardConfig config, std::u16string initial_text) {
+    Core::Frontend::SoftwareKeyboardParameters params{};
 
-SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
-                                   Core::Frontend::SoftwareKeyboardApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
+    params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+        config.submit_text.data(), config.submit_text.size());
+    params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+        config.header_text.data(), config.header_text.size());
+    params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(),
+                                                                       config.sub_text.size());
+    params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(),
+                                                                         config.guide_text.size());
+    params.initial_text = std::move(initial_text);
+    params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit;
+    params.password = static_cast<bool>(config.is_password);
+    params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position);
+    params.value = static_cast<u8>(config.keyset_disable_bitmask);
+
+    return params;
+}
+
+SoftwareKeyboard::SoftwareKeyboard(Core::System& system_,
+                                   const Core::Frontend::SoftwareKeyboardApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
 
 SoftwareKeyboard::~SoftwareKeyboard() = default;
 
 void SoftwareKeyboard::Initialize() {
+    complete = false;
+    is_inline = false;
+    initial_text.clear();
+    final_data.clear();
+
     Applet::Initialize();
 
-    LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
-             applet_mode);
+    const auto keyboard_config_storage = broker.PopNormalDataToApplet();
+    ASSERT(keyboard_config_storage != nullptr);
+    const auto& keyboard_config = keyboard_config_storage->GetData();
 
-    LOG_DEBUG(Service_AM,
-              "Initializing Applet with common_args: arg_version={}, lib_version={}, "
-              "play_startup_sound={}, size={}, system_tick={}, theme_color={}",
-              common_args.arguments_version, common_args.library_version,
-              common_args.play_startup_sound, common_args.size, common_args.system_tick,
-              common_args.theme_color);
-
-    swkbd_applet_version = SwkbdAppletVersion{common_args.library_version};
-
-    switch (applet_mode) {
-    case LibraryAppletMode::AllForeground:
-        InitializeForeground();
-        break;
-    case LibraryAppletMode::Background:
-    case LibraryAppletMode::BackgroundIndirectDisplay:
-        InitializeBackground(applet_mode);
-        break;
-    default:
-        UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode);
-        break;
+    if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
+        is_inline = true;
+        return;
     }
+
+    ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
+    std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
+
+    const auto work_buffer_storage = broker.PopNormalDataToApplet();
+    ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; });
+    const auto& work_buffer = work_buffer_storage->GetData();
+
+    if (config.initial_string_size == 0)
+        return;
+
+    std::vector<char16_t> string(config.initial_string_size);
+    std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset,
+                string.size() * 2);
+    initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size());
 }
 
 bool SoftwareKeyboard::TransactionComplete() const {
@@ -82,996 +95,106 @@ bool SoftwareKeyboard::TransactionComplete() const {
 }
 
 ResultCode SoftwareKeyboard::GetStatus() const {
-    return status;
+    return RESULT_SUCCESS;
 }
 
 void SoftwareKeyboard::ExecuteInteractive() {
-    if (complete) {
+    if (complete)
         return;
-    }
 
-    if (is_background) {
-        ProcessInlineKeyboardRequest();
+    const auto storage = broker.PopInteractiveDataToApplet();
+    ASSERT(storage != nullptr);
+    const auto data = storage->GetData();
+    if (!is_inline) {
+        const auto status = static_cast<bool>(data[0]);
+        if (status == INTERACTIVE_STATUS_OK) {
+            complete = true;
+        } else {
+            std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
+            std::memcpy(string.data(), data.data() + 4, string.size() * 2);
+            frontend.SendTextCheckDialog(
+                Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
+                [this] { broker.SignalStateChanged(); });
+        }
     } else {
-        ProcessTextCheck();
+        Request request{};
+        std::memcpy(&request, data.data(), sizeof(Request));
+
+        switch (request) {
+        case Request::Finalize:
+            complete = true;
+            broker.SignalStateChanged();
+            break;
+        case Request::Calc: {
+            broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1}));
+            broker.SignalStateChanged();
+            break;
+        }
+        default:
+            UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
+            break;
+        }
     }
 }
 
 void SoftwareKeyboard::Execute() {
     if (complete) {
+        broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
+        broker.SignalStateChanged();
         return;
     }
 
-    if (is_background) {
-        return;
-    }
-
-    ShowNormalKeyboard();
-}
-
-void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) {
-    if (complete) {
-        return;
-    }
-
-    if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) {
-        SubmitForTextCheck(submitted_text);
-    } else {
-        SubmitNormalOutputAndExit(result, submitted_text);
+    const auto parameters = ConvertToFrontendParameters(config, initial_text);
+    if (!is_inline) {
+        frontend.RequestText(
+            [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
     }
 }
 
-void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
-                                        s32 cursor_position) {
-    if (complete) {
-        return;
-    }
+void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
+    std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE);
 
-    current_text = std::move(submitted_text);
-    current_cursor_position = cursor_position;
+    if (text.has_value()) {
+        std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
 
-    if (inline_use_utf8) {
-        switch (reply_type) {
-        case SwkbdReplyType::ChangedString:
-            reply_type = SwkbdReplyType::ChangedStringUtf8;
-            break;
-        case SwkbdReplyType::MovedCursor:
-            reply_type = SwkbdReplyType::MovedCursorUtf8;
-            break;
-        case SwkbdReplyType::DecidedEnter:
-            reply_type = SwkbdReplyType::DecidedEnterUtf8;
-            break;
-        default:
-            break;
+        if (config.utf_8) {
+            const u64 size = text->size() + sizeof(u64);
+            const auto new_text = Common::UTF16ToUTF8(*text);
+
+            std::memcpy(output_sub.data(), &size, sizeof(u64));
+            std::memcpy(output_sub.data() + 8, new_text.data(),
+                        std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8));
+
+            output_main[0] = INTERACTIVE_STATUS_OK;
+            std::memcpy(output_main.data() + 4, new_text.data(),
+                        std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4));
+        } else {
+            const u64 size = text->size() * 2 + sizeof(u64);
+            std::memcpy(output_sub.data(), &size, sizeof(u64));
+            std::memcpy(output_sub.data() + 8, text->data(),
+                        std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8));
+
+            output_main[0] = INTERACTIVE_STATUS_OK;
+            std::memcpy(output_main.data() + 4, text->data(),
+                        std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
         }
-    }
 
-    if (use_changed_string_v2) {
-        switch (reply_type) {
-        case SwkbdReplyType::ChangedString:
-            reply_type = SwkbdReplyType::ChangedStringV2;
-            break;
-        case SwkbdReplyType::ChangedStringUtf8:
-            reply_type = SwkbdReplyType::ChangedStringUtf8V2;
-            break;
-        default:
-            break;
+        complete = !config.text_check;
+        final_data = output_main;
+
+        if (complete) {
+            broker.PushNormalDataFromApplet(
+                std::make_shared<IStorage>(system, std::move(output_main)));
+            broker.SignalStateChanged();
+        } else {
+            broker.PushInteractiveDataFromApplet(
+                std::make_shared<IStorage>(system, std::move(output_sub)));
         }
-    }
-
-    if (use_moved_cursor_v2) {
-        switch (reply_type) {
-        case SwkbdReplyType::MovedCursor:
-            reply_type = SwkbdReplyType::MovedCursorV2;
-            break;
-        case SwkbdReplyType::MovedCursorUtf8:
-            reply_type = SwkbdReplyType::MovedCursorUtf8V2;
-            break;
-        default:
-            break;
-        }
-    }
-
-    SendReply(reply_type);
-}
-
-void SoftwareKeyboard::InitializeForeground() {
-    LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet.");
-
-    is_background = false;
-
-    const auto swkbd_config_storage = broker.PopNormalDataToApplet();
-    ASSERT(swkbd_config_storage != nullptr);
-
-    const auto& swkbd_config_data = swkbd_config_storage->GetData();
-    ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon));
-
-    std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon));
-
-    switch (swkbd_applet_version) {
-    case SwkbdAppletVersion::Version5:
-    case SwkbdAppletVersion::Version65542:
-        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld));
-        std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
-                    sizeof(SwkbdConfigOld));
-        break;
-    case SwkbdAppletVersion::Version196615:
-    case SwkbdAppletVersion::Version262152:
-    case SwkbdAppletVersion::Version327689:
-        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2));
-        std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
-                    sizeof(SwkbdConfigOld2));
-        break;
-    case SwkbdAppletVersion::Version393227:
-    case SwkbdAppletVersion::Version524301:
-        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
-        std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
-                    sizeof(SwkbdConfigNew));
-        break;
-    default:
-        UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version,
-                          swkbd_config_data.size());
-        ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
-        std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
-                    sizeof(SwkbdConfigNew));
-        break;
-    }
-
-    const auto work_buffer_storage = broker.PopNormalDataToApplet();
-    ASSERT(work_buffer_storage != nullptr);
-
-    if (swkbd_config_common.initial_string_length == 0) {
-        InitializeFrontendKeyboard();
-        return;
-    }
-
-    const auto& work_buffer = work_buffer_storage->GetData();
-
-    std::vector<char16_t> initial_string(swkbd_config_common.initial_string_length);
-
-    std::memcpy(initial_string.data(),
-                work_buffer.data() + swkbd_config_common.initial_string_offset,
-                swkbd_config_common.initial_string_length * sizeof(char16_t));
-
-    initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(initial_string.data(),
-                                                                    initial_string.size());
-
-    LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text));
-
-    InitializeFrontendKeyboard();
-}
-
-void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) {
-    LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet.");
-
-    is_background = true;
-
-    const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet();
-    ASSERT(swkbd_inline_initialize_arg_storage != nullptr);
-
-    const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData();
-    ASSERT(swkbd_inline_initialize_arg.size() == sizeof(SwkbdInitializeArg));
-
-    std::memcpy(&swkbd_initialize_arg, swkbd_inline_initialize_arg.data(),
-                swkbd_inline_initialize_arg.size());
-
-    if (swkbd_initialize_arg.library_applet_mode_flag) {
-        ASSERT(applet_mode == LibraryAppletMode::Background);
     } else {
-        ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay);
+        output_main[0] = 1;
+        complete = true;
+        broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main)));
+        broker.SignalStateChanged();
     }
 }
-
-void SoftwareKeyboard::ProcessTextCheck() {
-    const auto text_check_storage = broker.PopInteractiveDataToApplet();
-    ASSERT(text_check_storage != nullptr);
-
-    const auto& text_check_data = text_check_storage->GetData();
-    ASSERT(text_check_data.size() == sizeof(SwkbdTextCheck));
-
-    SwkbdTextCheck swkbd_text_check;
-
-    std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck));
-
-    std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-        swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size());
-
-    LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}",
-             GetTextCheckResultName(swkbd_text_check.text_check_result),
-             Common::UTF16ToUTF8(text_check_message));
-
-    switch (swkbd_text_check.text_check_result) {
-    case SwkbdTextCheckResult::Success:
-        SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text);
-        break;
-    case SwkbdTextCheckResult::Failure:
-        ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message);
-        break;
-    case SwkbdTextCheckResult::Confirm:
-        ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message);
-        break;
-    case SwkbdTextCheckResult::Silent:
-    default:
-        break;
-    }
-}
-
-void SoftwareKeyboard::ProcessInlineKeyboardRequest() {
-    const auto request_data_storage = broker.PopInteractiveDataToApplet();
-    ASSERT(request_data_storage != nullptr);
-
-    const auto& request_data = request_data_storage->GetData();
-    ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand));
-
-    SwkbdRequestCommand request_command;
-
-    std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand));
-
-    switch (request_command) {
-    case SwkbdRequestCommand::Finalize:
-        RequestFinalize(request_data);
-        break;
-    case SwkbdRequestCommand::SetUserWordInfo:
-        RequestSetUserWordInfo(request_data);
-        break;
-    case SwkbdRequestCommand::SetCustomizeDic:
-        RequestSetCustomizeDic(request_data);
-        break;
-    case SwkbdRequestCommand::Calc:
-        RequestCalc(request_data);
-        break;
-    case SwkbdRequestCommand::SetCustomizedDictionaries:
-        RequestSetCustomizedDictionaries(request_data);
-        break;
-    case SwkbdRequestCommand::UnsetCustomizedDictionaries:
-        RequestUnsetCustomizedDictionaries(request_data);
-        break;
-    case SwkbdRequestCommand::SetChangedStringV2Flag:
-        RequestSetChangedStringV2Flag(request_data);
-        break;
-    case SwkbdRequestCommand::SetMovedCursorV2Flag:
-        RequestSetMovedCursorV2Flag(request_data);
-        break;
-    default:
-        UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command);
-        break;
-    }
-}
-
-void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
-                                                 std::u16string submitted_text) {
-    std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE);
-
-    if (swkbd_config_common.use_utf8) {
-        std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text);
-
-        LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result,
-                  utf8_submitted_text);
-
-        std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
-        std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(),
-                    utf8_submitted_text.size());
-    } else {
-        LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result,
-                  Common::UTF16ToUTF8(submitted_text));
-
-        std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
-        std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(),
-                    submitted_text.size() * sizeof(char16_t));
-    }
-
-    broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
-
-    ExitKeyboard();
-}
-
-void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
-    current_text = std::move(submitted_text);
-
-    std::vector<u8> out_data(sizeof(u64) + STRING_BUFFER_SIZE);
-
-    if (swkbd_config_common.use_utf8) {
-        std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text);
-        const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size();
-
-        LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size,
-                  utf8_submitted_text);
-
-        std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
-        std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(),
-                    utf8_submitted_text.size());
-    } else {
-        const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t);
-
-        LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size,
-                  Common::UTF16ToUTF8(current_text));
-
-        std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
-        std::memcpy(out_data.data() + sizeof(u64), current_text.data(),
-                    current_text.size() * sizeof(char16_t));
-    }
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
-}
-
-void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) {
-    switch (reply_type) {
-    case SwkbdReplyType::FinishedInitialize:
-        ReplyFinishedInitialize();
-        break;
-    case SwkbdReplyType::Default:
-        ReplyDefault();
-        break;
-    case SwkbdReplyType::ChangedString:
-        ReplyChangedString();
-        break;
-    case SwkbdReplyType::MovedCursor:
-        ReplyMovedCursor();
-        break;
-    case SwkbdReplyType::MovedTab:
-        ReplyMovedTab();
-        break;
-    case SwkbdReplyType::DecidedEnter:
-        ReplyDecidedEnter();
-        break;
-    case SwkbdReplyType::DecidedCancel:
-        ReplyDecidedCancel();
-        break;
-    case SwkbdReplyType::ChangedStringUtf8:
-        ReplyChangedStringUtf8();
-        break;
-    case SwkbdReplyType::MovedCursorUtf8:
-        ReplyMovedCursorUtf8();
-        break;
-    case SwkbdReplyType::DecidedEnterUtf8:
-        ReplyDecidedEnterUtf8();
-        break;
-    case SwkbdReplyType::UnsetCustomizeDic:
-        ReplyUnsetCustomizeDic();
-        break;
-    case SwkbdReplyType::ReleasedUserWordInfo:
-        ReplyReleasedUserWordInfo();
-        break;
-    case SwkbdReplyType::UnsetCustomizedDictionaries:
-        ReplyUnsetCustomizedDictionaries();
-        break;
-    case SwkbdReplyType::ChangedStringV2:
-        ReplyChangedStringV2();
-        break;
-    case SwkbdReplyType::MovedCursorV2:
-        ReplyMovedCursorV2();
-        break;
-    case SwkbdReplyType::ChangedStringUtf8V2:
-        ReplyChangedStringUtf8V2();
-        break;
-    case SwkbdReplyType::MovedCursorUtf8V2:
-        ReplyMovedCursorUtf8V2();
-        break;
-    default:
-        UNIMPLEMENTED_MSG("Unknown SwkbdReplyType={}", reply_type);
-        ReplyDefault();
-        break;
-    }
-}
-
-void SoftwareKeyboard::ChangeState(SwkbdState state) {
-    swkbd_state = state;
-
-    ReplyDefault();
-}
-
-void SoftwareKeyboard::InitializeFrontendKeyboard() {
-    if (is_background) {
-        const auto& appear_arg = swkbd_calc_arg.appear_arg;
-
-        std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            appear_arg.ok_text.data(), appear_arg.ok_text.size());
-
-        const u32 max_text_length =
-            appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
-                ? appear_arg.max_text_length
-                : DEFAULT_MAX_TEXT_LENGTH;
-
-        const u32 min_text_length =
-            appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
-
-        const s32 initial_cursor_position =
-            current_cursor_position > 0 ? current_cursor_position : 0;
-
-        const auto text_draw_type =
-            max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
-
-        Core::Frontend::KeyboardInitializeParameters initialize_parameters{
-            .ok_text{ok_text},
-            .header_text{},
-            .sub_text{},
-            .guide_text{},
-            .initial_text{current_text},
-            .max_text_length{max_text_length},
-            .min_text_length{min_text_length},
-            .initial_cursor_position{initial_cursor_position},
-            .type{appear_arg.type},
-            .password_mode{SwkbdPasswordMode::Disabled},
-            .text_draw_type{text_draw_type},
-            .key_disable_flags{appear_arg.key_disable_flags},
-            .use_blur_background{false},
-            .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
-            .enable_return_button{appear_arg.enable_return_button},
-            .disable_cancel_button{appear_arg.disable_cancel_button},
-        };
-
-        frontend.InitializeKeyboard(
-            true, std::move(initialize_parameters), {},
-            [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) {
-                SubmitTextInline(reply_type, submitted_text, cursor_position);
-            });
-    } else {
-        std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size());
-
-        std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size());
-
-        std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size());
-
-        std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size());
-
-        const u32 max_text_length =
-            swkbd_config_common.max_text_length > 0 &&
-                    swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
-                ? swkbd_config_common.max_text_length
-                : DEFAULT_MAX_TEXT_LENGTH;
-
-        const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length
-                                        ? swkbd_config_common.min_text_length
-                                        : 0;
-
-        const s32 initial_cursor_position = [this] {
-            switch (swkbd_config_common.initial_cursor_position) {
-            case SwkbdInitialCursorPosition::Start:
-            default:
-                return 0;
-            case SwkbdInitialCursorPosition::End:
-                return static_cast<s32>(initial_text.size());
-            }
-        }();
-
-        const auto text_draw_type = [this, max_text_length] {
-            switch (swkbd_config_common.text_draw_type) {
-            case SwkbdTextDrawType::Line:
-            default:
-                return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
-            case SwkbdTextDrawType::Box:
-            case SwkbdTextDrawType::DownloadCode:
-                return swkbd_config_common.text_draw_type;
-            }
-        }();
-
-        const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box
-                                              ? swkbd_config_common.enable_return_button
-                                              : false;
-
-        const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227
-                                               ? swkbd_config_new.disable_cancel_button
-                                               : false;
-
-        Core::Frontend::KeyboardInitializeParameters initialize_parameters{
-            .ok_text{ok_text},
-            .header_text{header_text},
-            .sub_text{sub_text},
-            .guide_text{guide_text},
-            .initial_text{initial_text},
-            .max_text_length{max_text_length},
-            .min_text_length{min_text_length},
-            .initial_cursor_position{initial_cursor_position},
-            .type{swkbd_config_common.type},
-            .password_mode{swkbd_config_common.password_mode},
-            .text_draw_type{text_draw_type},
-            .key_disable_flags{swkbd_config_common.key_disable_flags},
-            .use_blur_background{swkbd_config_common.use_blur_background},
-            .enable_backspace_button{true},
-            .enable_return_button{enable_return_button},
-            .disable_cancel_button{disable_cancel_button},
-        };
-
-        frontend.InitializeKeyboard(false, std::move(initialize_parameters),
-                                    [this](SwkbdResult result, std::u16string submitted_text) {
-                                        SubmitTextNormal(result, submitted_text);
-                                    },
-                                    {});
-    }
-}
-
-void SoftwareKeyboard::ShowNormalKeyboard() {
-    frontend.ShowNormalKeyboard();
-}
-
-void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
-                                           std::u16string text_check_message) {
-    frontend.ShowTextCheckDialog(text_check_result, text_check_message);
-}
-
-void SoftwareKeyboard::ShowInlineKeyboard() {
-    if (swkbd_state != SwkbdState::InitializedIsHidden) {
-        return;
-    }
-
-    ChangeState(SwkbdState::InitializedIsAppearing);
-
-    const auto& appear_arg = swkbd_calc_arg.appear_arg;
-
-    const u32 max_text_length =
-        appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
-            ? appear_arg.max_text_length
-            : DEFAULT_MAX_TEXT_LENGTH;
-
-    const u32 min_text_length =
-        appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
-
-    Core::Frontend::InlineAppearParameters appear_parameters{
-        .max_text_length{max_text_length},
-        .min_text_length{min_text_length},
-        .key_top_scale_x{swkbd_calc_arg.key_top_scale_x},
-        .key_top_scale_y{swkbd_calc_arg.key_top_scale_y},
-        .key_top_translate_x{swkbd_calc_arg.key_top_translate_x},
-        .key_top_translate_y{swkbd_calc_arg.key_top_translate_y},
-        .type{appear_arg.type},
-        .key_disable_flags{appear_arg.key_disable_flags},
-        .key_top_as_floating{swkbd_calc_arg.key_top_as_floating},
-        .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
-        .enable_return_button{appear_arg.enable_return_button},
-        .disable_cancel_button{appear_arg.disable_cancel_button},
-    };
-
-    frontend.ShowInlineKeyboard(std::move(appear_parameters));
-
-    ChangeState(SwkbdState::InitializedIsShown);
-}
-
-void SoftwareKeyboard::HideInlineKeyboard() {
-    if (swkbd_state != SwkbdState::InitializedIsShown) {
-        return;
-    }
-
-    ChangeState(SwkbdState::InitializedIsDisappearing);
-
-    frontend.HideInlineKeyboard();
-
-    ChangeState(SwkbdState::InitializedIsHidden);
-}
-
-void SoftwareKeyboard::InlineTextChanged() {
-    Core::Frontend::InlineTextParameters text_parameters{
-        .input_text{current_text},
-        .cursor_position{current_cursor_position},
-    };
-
-    frontend.InlineTextChanged(std::move(text_parameters));
-}
-
-void SoftwareKeyboard::ExitKeyboard() {
-    complete = true;
-    status = RESULT_SUCCESS;
-
-    frontend.ExitKeyboard();
-
-    broker.SignalStateChanged();
-}
-
-// Inline Software Keyboard Requests
-
-void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) {
-    LOG_DEBUG(Service_AM, "Processing Request: Finalize");
-
-    ChangeState(SwkbdState::NotInitialized);
-
-    ExitKeyboard();
-}
-
-void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) {
-    LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented.");
-}
-
-void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) {
-    LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented.");
-}
-
-void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) {
-    LOG_DEBUG(Service_AM, "Processing Request: Calc");
-
-    ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg));
-
-    std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand),
-                sizeof(SwkbdCalcArg));
-
-    if (swkbd_calc_arg.flags.set_input_text) {
-        current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
-            swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size());
-    }
-
-    if (swkbd_calc_arg.flags.set_cursor_position) {
-        current_cursor_position = swkbd_calc_arg.cursor_position;
-    }
-
-    if (swkbd_calc_arg.flags.set_utf8_mode) {
-        inline_use_utf8 = swkbd_calc_arg.utf8_mode;
-    }
-
-    if (swkbd_state <= SwkbdState::InitializedIsHidden &&
-        swkbd_calc_arg.flags.unset_customize_dic) {
-        ReplyUnsetCustomizeDic();
-    }
-
-    if (swkbd_state <= SwkbdState::InitializedIsHidden &&
-        swkbd_calc_arg.flags.unset_user_word_info) {
-        ReplyReleasedUserWordInfo();
-    }
-
-    if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) {
-        InitializeFrontendKeyboard();
-
-        ChangeState(SwkbdState::InitializedIsHidden);
-
-        ReplyFinishedInitialize();
-    }
-
-    if (!swkbd_calc_arg.flags.set_initialize_arg &&
-        (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) {
-        InlineTextChanged();
-    }
-
-    if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) {
-        ShowInlineKeyboard();
-        return;
-    }
-
-    if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) {
-        HideInlineKeyboard();
-        return;
-    }
-}
-
-void SoftwareKeyboard::RequestSetCustomizedDictionaries(const std::vector<u8>& request_data) {
-    LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented.");
-}
-
-void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data) {
-    LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries");
-
-    ReplyUnsetCustomizedDictionaries();
-}
-
-void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector<u8>& request_data) {
-    LOG_DEBUG(Service_AM, "Processing Request: SetChangedStringV2Flag");
-
-    ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
-
-    std::memcpy(&use_changed_string_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
-}
-
-void SoftwareKeyboard::RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data) {
-    LOG_DEBUG(Service_AM, "Processing Request: SetMovedCursorV2Flag");
-
-    ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
-
-    std::memcpy(&use_moved_cursor_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
-}
-
-// Inline Software Keyboard Replies
-
-void SoftwareKeyboard::ReplyFinishedInitialize() {
-    LOG_DEBUG(Service_AM, "Sending Reply: FinishedInitialize");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + 1);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyDefault() {
-    LOG_DEBUG(Service_AM, "Sending Reply: Default");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyChangedString() {
-    LOG_DEBUG(Service_AM, "Sending Reply: ChangedString");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString);
-
-    const SwkbdChangedStringArg changed_string_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .dictionary_start_cursor_position{-1},
-        .dictionary_end_cursor_position{-1},
-        .cursor_position{current_cursor_position},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
-                sizeof(SwkbdChangedStringArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyMovedCursor() {
-    LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor);
-
-    const SwkbdMovedCursorArg moved_cursor_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .cursor_position{current_cursor_position},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
-                sizeof(SwkbdMovedCursorArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyMovedTab() {
-    LOG_DEBUG(Service_AM, "Sending Reply: MovedTab");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab);
-
-    const SwkbdMovedTabArg moved_tab_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .cursor_position{current_cursor_position},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg,
-                sizeof(SwkbdMovedTabArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyDecidedEnter() {
-    LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter);
-
-    const SwkbdDecidedEnterArg decided_enter_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg,
-                sizeof(SwkbdDecidedEnterArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-
-    HideInlineKeyboard();
-}
-
-void SoftwareKeyboard::ReplyDecidedCancel() {
-    LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-
-    HideInlineKeyboard();
-}
-
-void SoftwareKeyboard::ReplyChangedStringUtf8() {
-    LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8);
-
-    std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
-
-    const SwkbdChangedStringArg changed_string_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .dictionary_start_cursor_position{-1},
-        .dictionary_end_cursor_position{-1},
-        .cursor_position{current_cursor_position},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
-                sizeof(SwkbdChangedStringArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyMovedCursorUtf8() {
-    LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8);
-
-    std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
-
-    const SwkbdMovedCursorArg moved_cursor_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .cursor_position{current_cursor_position},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
-                sizeof(SwkbdMovedCursorArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
-    LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdDecidedEnterArg));
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnterUtf8);
-
-    std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
-
-    const SwkbdDecidedEnterArg decided_enter_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-    };
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg,
-                sizeof(SwkbdDecidedEnterArg));
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-
-    HideInlineKeyboard();
-}
-
-void SoftwareKeyboard::ReplyUnsetCustomizeDic() {
-    LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
-    LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
-    LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyChangedStringV2() {
-    LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg) + 1);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringV2);
-
-    const SwkbdChangedStringArg changed_string_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .dictionary_start_cursor_position{-1},
-        .dictionary_end_cursor_position{-1},
-        .cursor_position{current_cursor_position},
-    };
-
-    constexpr u8 flag = 0;
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
-                sizeof(SwkbdChangedStringArg));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg),
-                &flag, 1);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyMovedCursorV2() {
-    LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorV2);
-
-    const SwkbdMovedCursorArg moved_cursor_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .cursor_position{current_cursor_position},
-    };
-
-    constexpr u8 flag = 0;
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
-                current_text.size() * sizeof(char16_t));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
-                sizeof(SwkbdMovedCursorArg));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg),
-                &flag, 1);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
-    LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg) + 1);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8V2);
-
-    std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
-
-    const SwkbdChangedStringArg changed_string_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .dictionary_start_cursor_position{-1},
-        .dictionary_end_cursor_position{-1},
-        .cursor_position{current_cursor_position},
-    };
-
-    constexpr u8 flag = 0;
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
-                sizeof(SwkbdChangedStringArg));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg),
-                &flag, 1);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
-void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
-    LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2");
-
-    std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
-
-    SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8V2);
-
-    std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
-
-    const SwkbdMovedCursorArg moved_cursor_arg{
-        .text_length{static_cast<u32>(current_text.size())},
-        .cursor_position{current_cursor_position},
-    };
-
-    constexpr u8 flag = 0;
-
-    std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
-                sizeof(SwkbdMovedCursorArg));
-    std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg),
-                &flag, 1);
-
-    broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
-}
-
 } // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index 85aeb4eb1..1d260fef8 100755
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -1,14 +1,20 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu emulator team
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
 #pragma once
 
+#include <array>
+#include <string>
+#include <vector>
+
 #include "common/common_funcs.h"
 #include "common/common_types.h"
-#include "core/hle/result.h"
+#include "common/swap.h"
+#include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applets.h"
-#include "core/hle/service/am/applets/software_keyboard_types.h"
+
+union ResultCode;
 
 namespace Core {
 class System;
@@ -16,10 +22,45 @@ class System;
 
 namespace Service::AM::Applets {
 
+enum class KeysetDisable : u32 {
+    Space = 0x02,
+    Address = 0x04,
+    Percent = 0x08,
+    Slashes = 0x10,
+    Numbers = 0x40,
+    DownloadCode = 0x80,
+};
+
+struct KeyboardConfig {
+    INSERT_PADDING_BYTES(4);
+    std::array<char16_t, 9> submit_text;
+    u16_le left_symbol_key;
+    u16_le right_symbol_key;
+    INSERT_PADDING_BYTES(1);
+    KeysetDisable keyset_disable_bitmask;
+    u32_le initial_cursor_position;
+    std::array<char16_t, 65> header_text;
+    std::array<char16_t, 129> sub_text;
+    std::array<char16_t, 257> guide_text;
+    u32_le length_limit;
+    INSERT_PADDING_BYTES(4);
+    u32_le is_password;
+    INSERT_PADDING_BYTES(5);
+    bool utf_8;
+    bool draw_background;
+    u32_le initial_string_offset;
+    u32_le initial_string_size;
+    u32_le user_dictionary_offset;
+    u32_le user_dictionary_size;
+    bool text_check;
+    u64_le text_check_callback;
+};
+static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size.");
+
 class SoftwareKeyboard final : public Applet {
 public:
-    explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
-                              Core::Frontend::SoftwareKeyboardApplet& frontend_);
+    explicit SoftwareKeyboard(Core::System& system_,
+                              const Core::Frontend::SoftwareKeyboardApplet& frontend_);
     ~SoftwareKeyboard() override;
 
     void Initialize() override;
@@ -29,139 +70,17 @@ public:
     void ExecuteInteractive() override;
     void Execute() override;
 
-    /**
-     * Submits the input text to the application.
-     * If text checking is enabled, the application will verify the input text.
-     * If use_utf8 is enabled, the input text will be converted to UTF-8 prior to being submitted.
-     * This should only be used by the normal software keyboard.
-     *
-     * @param result SwkbdResult enum
-     * @param submitted_text UTF-16 encoded string
-     */
-    void SubmitTextNormal(SwkbdResult result, std::u16string submitted_text);
-
-    /**
-     * Submits the input text to the application.
-     * If utf8_mode is enabled, the input text will be converted to UTF-8 prior to being submitted.
-     * This should only be used by the inline software keyboard.
-     *
-     * @param reply_type SwkbdReplyType enum
-     * @param submitted_text UTF-16 encoded string
-     * @param cursor_position The current position of the text cursor
-     */
-    void SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
-                          s32 cursor_position);
+    void WriteText(std::optional<std::u16string> text);
 
 private:
-    /// Initializes the normal software keyboard.
-    void InitializeForeground();
+    const Core::Frontend::SoftwareKeyboardApplet& frontend;
 
-    /// Initializes the inline software keyboard.
-    void InitializeBackground(LibraryAppletMode applet_mode);
-
-    /// Processes the text check sent by the application.
-    void ProcessTextCheck();
-
-    /// Processes the inline software keyboard request command sent by the application.
-    void ProcessInlineKeyboardRequest();
-
-    /// Submits the input text and exits the applet.
-    void SubmitNormalOutputAndExit(SwkbdResult result, std::u16string submitted_text);
-
-    /// Submits the input text for text checking.
-    void SubmitForTextCheck(std::u16string submitted_text);
-
-    /// Sends a reply to the application after processing a request command.
-    void SendReply(SwkbdReplyType reply_type);
-
-    /// Changes the inline keyboard state.
-    void ChangeState(SwkbdState state);
-
-    /**
-     * Signals the frontend to initialize the software keyboard with common parameters.
-     * This initializes either the normal software keyboard or the inline software keyboard
-     * depending on the state of is_background.
-     * Note that this does not cause the keyboard to appear.
-     * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear.
-     */
-    void InitializeFrontendKeyboard();
-
-    /// Signals the frontend to show the normal software keyboard.
-    void ShowNormalKeyboard();
-
-    /// Signals the frontend to show the text check dialog.
-    void ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
-                             std::u16string text_check_message);
-
-    /// Signals the frontend to show the inline software keyboard.
-    void ShowInlineKeyboard();
-
-    /// Signals the frontend to hide the inline software keyboard.
-    void HideInlineKeyboard();
-
-    /// Signals the frontend that the current inline keyboard text has changed.
-    void InlineTextChanged();
-
-    /// Signals both the frontend and application that the software keyboard is exiting.
-    void ExitKeyboard();
-
-    // Inline Software Keyboard Requests
-
-    void RequestFinalize(const std::vector<u8>& request_data);
-    void RequestSetUserWordInfo(const std::vector<u8>& request_data);
-    void RequestSetCustomizeDic(const std::vector<u8>& request_data);
-    void RequestCalc(const std::vector<u8>& request_data);
-    void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data);
-    void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data);
-    void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data);
-    void RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data);
-
-    // Inline Software Keyboard Replies
-
-    void ReplyFinishedInitialize();
-    void ReplyDefault();
-    void ReplyChangedString();
-    void ReplyMovedCursor();
-    void ReplyMovedTab();
-    void ReplyDecidedEnter();
-    void ReplyDecidedCancel();
-    void ReplyChangedStringUtf8();
-    void ReplyMovedCursorUtf8();
-    void ReplyDecidedEnterUtf8();
-    void ReplyUnsetCustomizeDic();
-    void ReplyReleasedUserWordInfo();
-    void ReplyUnsetCustomizedDictionaries();
-    void ReplyChangedStringV2();
-    void ReplyMovedCursorV2();
-    void ReplyChangedStringUtf8V2();
-    void ReplyMovedCursorUtf8V2();
-
-    LibraryAppletMode applet_mode;
-    Core::Frontend::SoftwareKeyboardApplet& frontend;
-    Core::System& system;
-
-    SwkbdAppletVersion swkbd_applet_version;
-
-    SwkbdConfigCommon swkbd_config_common;
-    SwkbdConfigOld swkbd_config_old;
-    SwkbdConfigOld2 swkbd_config_old2;
-    SwkbdConfigNew swkbd_config_new;
+    KeyboardConfig config;
     std::u16string initial_text;
-
-    SwkbdState swkbd_state{SwkbdState::NotInitialized};
-    SwkbdInitializeArg swkbd_initialize_arg;
-    SwkbdCalcArg swkbd_calc_arg;
-    bool use_changed_string_v2{false};
-    bool use_moved_cursor_v2{false};
-    bool inline_use_utf8{false};
-    s32 current_cursor_position{};
-
-    std::u16string current_text;
-
-    bool is_background{false};
-
-    bool complete{false};
-    ResultCode status{RESULT_SUCCESS};
+    bool complete = false;
+    bool is_inline = false;
+    std::vector<u8> final_data;
+    Core::System& system;
 };
 
 } // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index b28b849bc..2ab420789 100755
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -208,9 +208,8 @@ void ExtractSharedFonts(Core::System& system) {
 
 } // namespace
 
-WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
-                       const Core::Frontend::WebBrowserApplet& frontend_)
-    : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend(frontend_), system{system_} {}
+WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_)
+    : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {}
 
 WebBrowser::~WebBrowser() = default;
 
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 5eafbae7b..04c274754 100755
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -25,8 +25,7 @@ namespace Service::AM::Applets {
 
 class WebBrowser final : public Applet {
 public:
-    WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
-               const Core::Frontend::WebBrowserApplet& frontend_);
+    WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_);
 
     ~WebBrowser() override;
 
@@ -64,7 +63,6 @@ private:
     void ExecuteWifi();
     void ExecuteLobby();
 
-    LibraryAppletMode applet_mode;
     const Core::Frontend::WebBrowserApplet& frontend;
 
     bool complete{false};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index b9d30927a..c8031970b 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -36,7 +36,6 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
                 LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
                 Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
                 system.GPU().PushCommandBuffer(cmdlist);
-                system.GPU().MemoryManager().InvalidateQueuedCaches();
             }
             return UnmapBuffer(input, output);
         }
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 6654aa66d..c2f152190 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -198,13 +198,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec
             return NvResult::InvalidState;
         }
         if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) {
-            if (vic_device) {
-                // UnmapVicFrame defers texture_cache invalidation of the frame address until
-                // the stream is over
-                gpu.MemoryManager().UnmapVicFrame(object->dma_map_addr, *size);
-            } else {
-                gpu.MemoryManager().Unmap(object->dma_map_addr, *size);
-            }
+            gpu.MemoryManager().Unmap(object->dma_map_addr, *size);
         } else {
             // This occurs quite frequently, however does not seem to impact functionality
             LOG_DEBUG(Service_NVDRV, "invalid offset=0x{:X} dma=0x{:X}", object->addr,
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index 2e0aece2f..4c9d4ba41 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -160,7 +160,6 @@ protected:
 
     s32_le nvmap_fd{};
     u32_le submit_timeout{};
-    bool vic_device{};
     std::shared_ptr<nvmap> nvmap_dev;
     SyncpointManager& syncpoint_manager;
     std::array<u32, MaxSyncPoints> device_syncpoints{};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 6c2f95fc0..0421fb956 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -12,9 +12,8 @@
 namespace Service::Nvidia::Devices {
 nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev,
                        SyncpointManager& syncpoint_manager)
-    : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) {
-    vic_device = true;
-}
+    : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) {}
+
 nvhost_vic::~nvhost_vic() = default;
 
 NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 51c26c6c3..f67de37e3 100755
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -761,7 +761,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
         for (const auto& joystick : value) {
             if (auto* const controller = joystick->GetSDLGameController()) {
                 std::string name =
-                    fmt::format("{} {}", GetControllerName(controller), joystick->GetPort());
+                    fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
                 devices.emplace_back(Common::ParamPackage{
                     {"class", "sdl"},
                     {"display", std::move(name)},
@@ -782,17 +782,6 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
     return devices;
 }
 
-std::string SDLState::GetControllerName(SDL_GameController* controller) const {
-    switch (SDL_GameControllerGetType(controller)) {
-    case SDL_CONTROLLER_TYPE_XBOX360:
-        return "XBox 360 Controller";
-    case SDL_CONTROLLER_TYPE_XBOXONE:
-        return "XBox One Controller";
-    default:
-        return SDL_GameControllerName(controller);
-    }
-}
-
 namespace {
 Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
                                                       float value = 0.1f) {
@@ -941,19 +930,16 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa
         return {};
     }
 
-    const bool invert =
-        SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
-
     // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
     // We will add those afterwards
     // This list also excludes Screenshot since theres not really a mapping for that
     using ButtonBindings =
         std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>;
-    const ButtonBindings switch_to_sdl_button{{
-        {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A},
-        {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B},
-        {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X},
-        {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y},
+    static constexpr ButtonBindings switch_to_sdl_button{{
+        {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
+        {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
+        {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
+        {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
         {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
         {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
         {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index 8b7363f56..08044b00d 100755
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -14,7 +14,6 @@
 #include "input_common/sdl/sdl.h"
 
 union SDL_Event;
-using SDL_GameController = struct _SDL_GameController;
 using SDL_Joystick = struct _SDL_Joystick;
 using SDL_JoystickID = s32;
 
@@ -65,9 +64,6 @@ private:
     /// Needs to be called before SDL_QuitSubSystem.
     void CloseJoysticks();
 
-    /// Returns a custom name for specific controllers because the default name is not correct
-    std::string GetControllerName(SDL_GameController* controller) const;
-
     // Set to true if SDL supports game controller subsystem
     bool has_gamecontroller = false;
 
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 5d659dcaf..8b45f1b62 100755
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1785,8 +1785,6 @@ public:
         SSY,
         SYNC,
         BRK,
-        CAL,
-        RET,
         DEPBAR,
         VOTE,
         VOTE_VTG,
@@ -2110,8 +2108,6 @@ private:
             INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"),
             INST("111000110100----", Id::BRK, Type::Flow, "BRK"),
             INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"),
-            INST("111000100110----", Id::CAL, Type::Flow, "CAL"),
-            INST("111000110010----", Id::RET, Type::Flow, "RET"),
             INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
             INST("0101000011011---", Id::VOTE, Type::Warp, "VOTE"),
             INST("0101000011100---", Id::VOTE_VTG, Type::Warp, "VOTE_VTG"),
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 9529a1256..4eb71efbd 100755
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -114,25 +114,6 @@ void MemoryManager::TryUnlockPage(PageEntry page_entry, std::size_t size) {
                .IsSuccess());
 }
 
-void MemoryManager::UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size) {
-    if (!size) {
-        return;
-    }
-
-    const std::optional<VAddr> cpu_addr = GpuToCpuAddress(gpu_addr);
-    ASSERT(cpu_addr);
-    rasterizer->InvalidateExceptTextureCache(*cpu_addr, size);
-    cache_invalidate_queue.push_back({*cpu_addr, size});
-
-    UpdateRange(gpu_addr, PageEntry::State::Unmapped, size);
-}
-
-void MemoryManager::InvalidateQueuedCaches() {
-    for (const auto& entry : cache_invalidate_queue) {
-        rasterizer->InvalidateTextureCache(entry.first, entry.second);
-    }
-    cache_invalidate_queue.clear();
-}
 PageEntry MemoryManager::GetPageEntry(GPUVAddr gpu_addr) const {
     return page_table[PageEntryIndex(gpu_addr)];
 }
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 5d6c196fa..b3538d503 100755
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -123,14 +123,6 @@ public:
     [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align);
     void Unmap(GPUVAddr gpu_addr, std::size_t size);
 
-    /**
-     * Some Decoded NVDEC frames require that texture cache does not get invalidated.
-     * UnmapVicFrame defers the texture cache invalidation until the stream ends
-     * by invoking InvalidateQueuedCaches to invalidate all frame texture caches.
-     */
-    void UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size);
-    void InvalidateQueuedCaches();
-
 private:
     [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const;
     void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size);
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index afc7ff4ae..50491b758 100755
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -69,12 +69,6 @@ public:
     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
     virtual void FlushRegion(VAddr addr, u64 size) = 0;
 
-    /// Notify rasterizer to flush the texture cache to Switch memory
-    virtual void InvalidateExceptTextureCache(VAddr addr, u64 size) = 0;
-
-    /// Notify rasterizer to invalidate the texture cache
-    virtual void InvalidateTextureCache(VAddr addr, u64 size) = 0;
-
     /// Check if the the specified memory area requires flushing to CPU Memory.
     virtual bool MustFlushRegion(VAddr addr, u64 size) = 0;
 
diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
index e98647478..3e4d88c30 100755
--- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
@@ -491,9 +491,6 @@ private:
     const Registry& registry;
     const ShaderType stage;
 
-    std::shared_ptr<ShaderFunctionIR> context_func;
-    u32 ast_var_base{};
-
     std::size_t num_temporaries = 0;
     std::size_t max_temporaries = 0;
 
@@ -810,33 +807,13 @@ ARBDecompiler::ARBDecompiler(const Device& device_, const ShaderIR& ir_, const R
     : device{device_}, ir{ir_}, registry{registry_}, stage{stage_} {
     DefineGlobalMemory();
 
-    context_func = ir.GetMainFunction();
-    ast_var_base = 0;
-
     AddLine("TEMP RC;");
     AddLine("TEMP FSWZA[4];");
     AddLine("TEMP FSWZB[4];");
-    InitializeVariables();
-    AddLine("main:");
-    if (context_func->IsDecompiled()) {
+    if (ir.IsDecompiled()) {
         DecompileAST();
     } else {
         DecompileBranchMode();
-        AddLine("RET;");
-    }
-
-    const auto& subfunctions = ir.GetSubFunctions();
-    auto it = subfunctions.begin();
-    while (it != subfunctions.end()) {
-        context_func = *it;
-        AddLine("func_{}:", context_func->GetId());
-        if (context_func->IsDecompiled()) {
-            DecompileAST();
-        } else {
-            DecompileBranchMode();
-            AddLine("RET;");
-        }
-        it++;
     }
     AddLine("END");
 
@@ -1083,38 +1060,41 @@ void ARBDecompiler::InitializeVariables() {
 }
 
 void ARBDecompiler::DecompileAST() {
-    const u32 num_flow_variables = context_func->GetASTNumVariables();
+    const u32 num_flow_variables = ir.GetASTNumVariables();
     for (u32 i = 0; i < num_flow_variables; ++i) {
-        AddLine("TEMP F{};", i + ast_var_base);
+        AddLine("TEMP F{};", i);
     }
     for (u32 i = 0; i < num_flow_variables; ++i) {
-        AddLine("MOV.U F{}, {{0, 0, 0, 0}};", i + ast_var_base);
+        AddLine("MOV.U F{}, {{0, 0, 0, 0}};", i);
     }
 
-    VisitAST(context_func->GetASTProgram());
-    ast_var_base += num_flow_variables;
+    InitializeVariables();
+
+    VisitAST(ir.GetASTProgram());
 }
 
 void ARBDecompiler::DecompileBranchMode() {
     static constexpr u32 FLOW_STACK_SIZE = 20;
-    if (!context_func->IsFlowStackDisabled()) {
+    if (!ir.IsFlowStackDisabled()) {
         AddLine("TEMP SSY[{}];", FLOW_STACK_SIZE);
         AddLine("TEMP PBK[{}];", FLOW_STACK_SIZE);
         AddLine("TEMP SSY_TOP;");
         AddLine("TEMP PBK_TOP;");
     }
 
-    AddLine("TEMP PC{};", context_func->GetId());
+    AddLine("TEMP PC;");
 
-    if (!context_func->IsFlowStackDisabled()) {
+    if (!ir.IsFlowStackDisabled()) {
         AddLine("MOV.U SSY_TOP.x, 0;");
         AddLine("MOV.U PBK_TOP.x, 0;");
     }
 
-    const auto basic_block_end = context_func->GetBasicBlocks().end();
-    auto basic_block_it = context_func->GetBasicBlocks().begin();
+    InitializeVariables();
+
+    const auto basic_block_end = ir.GetBasicBlocks().end();
+    auto basic_block_it = ir.GetBasicBlocks().begin();
     const u32 first_address = basic_block_it->first;
-    AddLine("MOV.U PC{}.x, {};", context_func->GetId(), first_address);
+    AddLine("MOV.U PC.x, {};", first_address);
 
     AddLine("REP;");
 
@@ -1123,7 +1103,7 @@ void ARBDecompiler::DecompileBranchMode() {
         const auto& [address, bb] = *basic_block_it;
         ++num_blocks;
 
-        AddLine("SEQ.S.CC RC.x, PC{}.x, {};", context_func->GetId(), address);
+        AddLine("SEQ.S.CC RC.x, PC.x, {};", address);
         AddLine("IF NE.x;");
 
         VisitBlock(bb);
@@ -1134,7 +1114,7 @@ void ARBDecompiler::DecompileBranchMode() {
             const auto op = std::get_if<OperationNode>(&*bb[bb.size() - 1]);
             if (!op || op->GetCode() != OperationCode::Branch) {
                 const u32 next_address = basic_block_it->first;
-                AddLine("MOV.U PC{}.x, {};", context_func->GetId(), next_address);
+                AddLine("MOV.U PC.x, {};", next_address);
                 AddLine("CONT;");
             }
         }
@@ -1172,8 +1152,7 @@ void ARBDecompiler::VisitAST(const ASTNode& node) {
     } else if (const auto decoded = std::get_if<ASTBlockDecoded>(&*node->GetInnerData())) {
         VisitBlock(decoded->nodes);
     } else if (const auto var_set = std::get_if<ASTVarSet>(&*node->GetInnerData())) {
-        AddLine("MOV.U F{}, {};", var_set->index + ast_var_base,
-                VisitExpression(var_set->condition));
+        AddLine("MOV.U F{}, {};", var_set->index, VisitExpression(var_set->condition));
         ResetTemporaries();
     } else if (const auto do_while = std::get_if<ASTDoWhile>(&*node->GetInnerData())) {
         const std::string condition = VisitExpression(do_while->condition);
@@ -1193,11 +1172,7 @@ void ARBDecompiler::VisitAST(const ASTNode& node) {
             ResetTemporaries();
         }
         if (ast_return->kills) {
-            if (stage == ShaderType::Fragment) {
-                AddLine("KIL TR;");
-            } else {
-                AddLine("RET;");
-            }
+            AddLine("KIL TR;");
         } else {
             Exit();
         }
@@ -1244,7 +1219,7 @@ std::string ARBDecompiler::VisitExpression(const Expr& node) {
         return Visit(ir.GetConditionCode(expr->cc));
     }
     if (const auto expr = std::get_if<ExprVar>(&*node)) {
-        return fmt::format("F{}.x", expr->var_index + ast_var_base);
+        return fmt::format("F{}.x", expr->var_index);
     }
     if (const auto expr = std::get_if<ExprBoolean>(&*node)) {
         return expr->value ? "0xffffffff" : "0";
@@ -1431,11 +1406,6 @@ std::string ARBDecompiler::Visit(const Node& node) {
         return {};
     }
 
-    if (const auto func_call = std::get_if<FunctionCallNode>(&*node)) {
-        AddLine("CAL func_{};", func_call->GetFuncId());
-        return {};
-    }
-
     if ([[maybe_unused]] const auto cmt = std::get_if<CommentNode>(&*node)) {
         // Uncommenting this will generate invalid code. GLASM lacks comments.
         // AddLine("// {}", cmt->GetText());
@@ -1509,7 +1479,7 @@ std::string ARBDecompiler::GlobalMemoryPointer(const GmemNode& gmem) {
 }
 
 void ARBDecompiler::Exit() {
-    if (!context_func->IsMain() || stage != ShaderType::Fragment) {
+    if (stage != ShaderType::Fragment) {
         AddLine("RET;");
         return;
     }
@@ -2051,13 +2021,13 @@ std::string ARBDecompiler::ImageStore(Operation operation) {
 
 std::string ARBDecompiler::Branch(Operation operation) {
     const auto target = std::get<ImmediateNode>(*operation[0]);
-    AddLine("MOV.U PC{}.x, {};", context_func->GetId(), target.GetValue());
+    AddLine("MOV.U PC.x, {};", target.GetValue());
     AddLine("CONT;");
     return {};
 }
 
 std::string ARBDecompiler::BranchIndirect(Operation operation) {
-    AddLine("MOV.U PC{}.x, {};", context_func->GetId(), Visit(operation[0]));
+    AddLine("MOV.U PC.x, {};", Visit(operation[0]));
     AddLine("CONT;");
     return {};
 }
@@ -2075,7 +2045,7 @@ std::string ARBDecompiler::PopFlowStack(Operation operation) {
     const auto stack = std::get<MetaStackClass>(operation.GetMeta());
     const std::string_view stack_name = StackName(stack);
     AddLine("SUB.S {}_TOP.x, {}_TOP.x, 1;", stack_name, stack_name);
-    AddLine("MOV.U PC{}.x, {}[{}_TOP.x].x;", context_func->GetId(), stack_name, stack_name);
+    AddLine("MOV.U PC.x, {}[{}_TOP.x].x;", stack_name, stack_name);
     AddLine("CONT;");
     return {};
 }
@@ -2086,10 +2056,6 @@ std::string ARBDecompiler::Exit(Operation) {
 }
 
 std::string ARBDecompiler::Discard(Operation) {
-    if (stage != ShaderType::Fragment) {
-        AddLine("RET;");
-        return {};
-    }
     AddLine("KIL TR;");
     return {};
 }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a7f7733eb..4610fd160 100755
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -544,26 +544,6 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
     query_cache.FlushRegion(addr, size);
 }
 
-void RasterizerOpenGL::InvalidateExceptTextureCache(VAddr addr, u64 size) {
-    if (addr == 0 || size == 0) {
-        return;
-    }
-    shader_cache.InvalidateRegion(addr, size);
-    {
-        std::scoped_lock lock{buffer_cache.mutex};
-        buffer_cache.WriteMemory(addr, size);
-    }
-    query_cache.InvalidateRegion(addr, size);
-}
-
-void RasterizerOpenGL::InvalidateTextureCache(VAddr addr, u64 size) {
-    if (addr == 0 || size == 0) {
-        return;
-    }
-    std::scoped_lock lock{texture_cache.mutex};
-    texture_cache.UnmapMemory(addr, size);
-}
-
 bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) {
     std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
     if (!Settings::IsGPULevelHigh()) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 9730544d9..3745cf637 100755
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -74,8 +74,6 @@ public:
     void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
     void FlushAll() override;
     void FlushRegion(VAddr addr, u64 size) override;
-    void InvalidateExceptTextureCache(VAddr addr, u64 size) override;
-    void InvalidateTextureCache(VAddr addr, u64 size) override;
     bool MustFlushRegion(VAddr addr, u64 size) override;
     void InvalidateRegion(VAddr addr, u64 size) override;
     void OnCPUWrite(VAddr addr, u64 size) override;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index fd49014b9..ac78d344c 100755
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -79,11 +79,6 @@ const float fswzadd_modifiers_a[] = float[4](-1.0f,  1.0f, -1.0f,  0.0f );
 const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f,  1.0f, -1.0f );
 )";
 
-enum class HelperFunction {
-    SignedAtomic = 0,
-    Total,
-};
-
 class ShaderWriter final {
 public:
     void AddExpression(std::string_view text) {
@@ -439,28 +434,6 @@ public:
         DeclareInternalFlags();
         DeclareCustomVariables();
         DeclarePhysicalAttributeReader();
-        DeclareHelpersForward();
-
-        const auto& subfunctions = ir.GetSubFunctions();
-        auto it = subfunctions.rbegin();
-        while (it != subfunctions.rend()) {
-            context_func = *it;
-            code.AddLine("void func_{}() {{", context_func->GetId());
-            ++code.scope;
-
-            if (context_func->IsDecompiled()) {
-                DecompileAST();
-            } else {
-                DecompileBranchMode();
-            }
-
-            --code.scope;
-            code.AddLine("}}");
-
-            it++;
-        }
-
-        context_func = ir.GetMainFunction();
 
         code.AddLine("void main() {{");
         ++code.scope;
@@ -469,7 +442,7 @@ public:
             code.AddLine("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);");
         }
 
-        if (context_func->IsDecompiled()) {
+        if (ir.IsDecompiled()) {
             DecompileAST();
         } else {
             DecompileBranchMode();
@@ -477,9 +450,6 @@ public:
 
         --code.scope;
         code.AddLine("}}");
-
-        code.AddNewLine();
-        DeclareHelpers();
     }
 
     std::string GetResult() {
@@ -492,13 +462,13 @@ private:
 
     void DecompileBranchMode() {
         // VM's program counter
-        const auto first_address = context_func->GetBasicBlocks().begin()->first;
+        const auto first_address = ir.GetBasicBlocks().begin()->first;
         code.AddLine("uint jmp_to = {}U;", first_address);
 
         // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
         // unlikely that shaders will use 20 nested SSYs and PBKs.
         constexpr u32 FLOW_STACK_SIZE = 20;
-        if (!context_func->IsFlowStackDisabled()) {
+        if (!ir.IsFlowStackDisabled()) {
             for (const auto stack : std::array{MetaStackClass::Ssy, MetaStackClass::Pbk}) {
                 code.AddLine("uint {}[{}];", FlowStackName(stack), FLOW_STACK_SIZE);
                 code.AddLine("uint {} = 0U;", FlowStackTopName(stack));
@@ -510,7 +480,7 @@ private:
 
         code.AddLine("switch (jmp_to) {{");
 
-        for (const auto& pair : context_func->GetBasicBlocks()) {
+        for (const auto& pair : ir.GetBasicBlocks()) {
             const auto& [address, bb] = pair;
             code.AddLine("case 0x{:X}U: {{", address);
             ++code.scope;
@@ -629,7 +599,7 @@ private:
                 size = limit;
             }
 
-            code.AddLine("shared uint {}[{}];", GetSharedMemory(), size / 4);
+            code.AddLine("shared uint smem[{}];", size / 4);
             code.AddNewLine();
         }
         code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;",
@@ -1013,27 +983,6 @@ private:
         }
     }
 
-    void DeclareHelpersForward() {
-        code.AddLine("int Helpers_AtomicShared(uint offset, int value, bool is_min);");
-        code.AddNewLine();
-    }
-
-    void DeclareHelpers() {
-        if (IsHelperEnabled(HelperFunction::SignedAtomic)) {
-            code.AddLine(
-                R"(int Helpers_AtomicShared(uint offset, int value, bool is_min) {{
-    uint oldValue, newValue;
-    do {{
-        oldValue = {}[offset];
-        newValue = is_min ? uint(min(int(oldValue), value)) : uint(max(int(oldValue), value));
-    }} while (atomicCompSwap({}[offset], newValue, oldValue) != oldValue);
-    return int(oldValue);
-}})",
-                GetSharedMemory(), GetSharedMemory());
-            code.AddNewLine();
-        }
-    }
-
     void VisitBlock(const NodeBlock& bb) {
         for (const auto& node : bb) {
             Visit(node).CheckVoid();
@@ -1160,9 +1109,7 @@ private:
         }
 
         if (const auto smem = std::get_if<SmemNode>(&*node)) {
-            return {
-                fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
-                Type::Uint};
+            return {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint};
         }
 
         if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) {
@@ -1184,11 +1131,6 @@ private:
             return {};
         }
 
-        if (const auto func_call = std::get_if<FunctionCallNode>(&*node)) {
-            code.AddLine("func_{}();", func_call->GetFuncId());
-            return {};
-        }
-
         if (const auto comment = std::get_if<CommentNode>(&*node)) {
             code.AddLine("// " + comment->GetText());
             return {};
@@ -1656,9 +1598,7 @@ private:
                 Type::Uint};
         } else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
             ASSERT(stage == ShaderType::Compute);
-            target = {
-                fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
-                Type::Uint};
+            target = {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint};
         } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
             const std::string real = Visit(gmem->GetRealAddress()).AsUint();
             const std::string base = Visit(gmem->GetBaseAddress()).AsUint();
@@ -2175,14 +2115,7 @@ private:
         UNIMPLEMENTED_IF(meta->sampler.is_array);
         const std::size_t count = operation.GetOperandsCount();
 
-        std::string expr = "texelFetch";
-
-        if (!meta->aoffi.empty()) {
-            expr += "Offset";
-        }
-
-        expr += '(';
-
+        std::string expr = "texelFetch(";
         expr += GetSampler(meta->sampler);
         expr += ", ";
 
@@ -2204,20 +2137,6 @@ private:
             expr += ", ";
             expr += Visit(meta->lod).AsInt();
         }
-
-        if (!meta->aoffi.empty()) {
-            expr += ", ";
-            expr += constructors.at(meta->aoffi.size() - 1);
-            expr += '(';
-            for (size_t i = 0; i < meta->aoffi.size(); ++i) {
-                if (i > 0) {
-                    expr += ", ";
-                }
-                expr += Visit(meta->aoffi[i]).AsInt();
-            }
-            expr += ')';
-        }
-
         expr += ')';
         expr += GetSwizzle(meta->element);
 
@@ -2264,11 +2183,8 @@ private:
     template <const std::string_view& opname, Type type>
     Expression Atomic(Operation operation) {
         if ((opname == Func::Min || opname == Func::Max) && type == Type::Int) {
-            // Use a helper as a workaround due to memory being uint
-            SetHelperEnabled(HelperFunction::SignedAtomic, true);
-            return {fmt::format("Helpers_AtomicShared({}, {}, {})", Visit(operation[0]).AsInt(),
-                                Visit(operation[1]).AsInt(), opname == Func::Min),
-                    Type::Int};
+            UNIMPLEMENTED_MSG("Unimplemented Min & Max for atomic operations");
+            return {};
         }
         return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(),
                             Visit(operation[1]).AsUint()),
@@ -2351,9 +2267,7 @@ private:
     }
 
     Expression Exit(Operation operation) {
-        if (context_func->IsMain()) {
-            PreExit();
-        }
+        PreExit();
         code.AddLine("return;");
         return {};
     }
@@ -2363,11 +2277,7 @@ private:
         // about unexecuted instructions that may follow this.
         code.AddLine("if (true) {{");
         ++code.scope;
-        if (stage != ShaderType::Fragment) {
-            code.AddLine("return;");
-        } else {
-            code.AddLine("discard;");
-        }
+        code.AddLine("discard;");
         --code.scope;
         code.AddLine("}}");
         return {};
@@ -2478,7 +2388,7 @@ private:
     }
 
     Expression Barrier(Operation) {
-        if (!context_func->IsDecompiled()) {
+        if (!ir.IsDecompiled()) {
             LOG_ERROR(Render_OpenGL, "barrier() used but shader is not decompiled");
             return {};
         }
@@ -2795,10 +2705,6 @@ private:
         }
     }
 
-    constexpr std::string_view GetSharedMemory() const {
-        return "shared_mem";
-    }
-
     std::string GetInternalFlag(InternalFlag flag) const {
         constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag",
                                                   "overflow_flag"};
@@ -2840,14 +2746,6 @@ private:
         return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings);
     }
 
-    void SetHelperEnabled(HelperFunction hf, bool enabled) {
-        helper_functions_enabled[static_cast<size_t>(hf)] = enabled;
-    }
-
-    bool IsHelperEnabled(HelperFunction hf) const {
-        return helper_functions_enabled[static_cast<size_t>(hf)];
-    }
-
     const Device& device;
     const ShaderIR& ir;
     const Registry& registry;
@@ -2857,13 +2755,9 @@ private:
     const Header header;
     std::unordered_map<u8, VaryingTFB> transform_feedback;
 
-    std::shared_ptr<ShaderFunctionIR> context_func;
-
     ShaderWriter code;
 
     std::optional<u32> max_input_vertices;
-
-    std::array<bool, static_cast<size_t>(HelperFunction::Total)> helper_functions_enabled{};
 };
 
 std::string GetFlowVariable(u32 index) {
@@ -3008,15 +2902,9 @@ public:
             decomp.code.scope++;
         }
         if (ast.kills) {
-            if (decomp.stage != ShaderType::Fragment) {
-                decomp.code.AddLine("return;");
-            } else {
-                decomp.code.AddLine("discard;");
-            }
+            decomp.code.AddLine("discard;");
         } else {
-            if (decomp.context_func->IsMain()) {
-                decomp.PreExit();
-            }
+            decomp.PreExit();
             decomp.code.AddLine("return;");
         }
         if (!is_true) {
@@ -3049,13 +2937,13 @@ private:
 };
 
 void GLSLDecompiler::DecompileAST() {
-    const u32 num_flow_variables = context_func->GetASTNumVariables();
+    const u32 num_flow_variables = ir.GetASTNumVariables();
     for (u32 i = 0; i < num_flow_variables; i++) {
         code.AddLine("bool {} = false;", GetFlowVariable(i));
     }
 
     ASTDecompiler decompiler{*this};
-    decompiler.Visit(context_func->GetASTProgram());
+    decompiler.Visit(ir.GetASTProgram());
 }
 
 } // Anonymous namespace
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 69a0faca3..df5b7b172 100755
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -493,26 +493,6 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) {
     query_cache.FlushRegion(addr, size);
 }
 
-void Vulkan::RasterizerVulkan::InvalidateExceptTextureCache(VAddr addr, u64 size) {
-    if (addr == 0 || size == 0) {
-        return;
-    }
-    pipeline_cache.InvalidateRegion(addr, size);
-    {
-        std::scoped_lock lock{buffer_cache.mutex};
-        buffer_cache.WriteMemory(addr, size);
-    }
-    query_cache.InvalidateRegion(addr, size);
-}
-
-void Vulkan::RasterizerVulkan::InvalidateTextureCache(VAddr addr, u64 size) {
-    if (addr == 0 || size == 0) {
-        return;
-    }
-    std::scoped_lock lock{texture_cache.mutex};
-    texture_cache.UnmapMemory(addr, size);
-}
-
 bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size) {
     std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex};
     if (!Settings::IsGPULevelHigh()) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index d8b5bf0fc..235afc6f3 100755
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -66,8 +66,6 @@ public:
     void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
     void FlushAll() override;
     void FlushRegion(VAddr addr, u64 size) override;
-    void InvalidateExceptTextureCache(VAddr addr, u64 size) override;
-    void InvalidateTextureCache(VAddr addr, u64 size) override;
     bool MustFlushRegion(VAddr addr, u64 size) override;
     void InvalidateRegion(VAddr addr, u64 size) override;
     void OnCPUWrite(VAddr addr, u64 size) override;
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 258e2f5df..c6846d886 100755
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -406,38 +406,10 @@ private:
         binding = DeclareStorageTexels(binding);
         binding = DeclareImages(binding);
 
-        const auto& subfunctions = ir.GetSubFunctions();
-
-        labels.resize(subfunctions.size() + 1);
-        other_functions.resize(subfunctions.size());
-
-        auto it = subfunctions.rbegin();
-        while (it != subfunctions.rend()) {
-            context_func = *it;
-            other_functions[context_func->GetId() - 1] =
-                OpFunction(t_void, {}, TypeFunction(t_void));
-            AddLabel();
-
-            if (context_func->IsDecompiled()) {
-                DeclareFlowVariables();
-                DecompileAST();
-            } else {
-                AllocateLabels();
-                DecompileBranchMode();
-            }
-
-            OpReturn();
-            OpFunctionEnd();
-
-            it++;
-        }
-
-        context_func = ir.GetMainFunction();
-
         const Id main = OpFunction(t_void, {}, TypeFunction(t_void));
         AddLabel();
 
-        if (context_func->IsDecompiled()) {
+        if (ir.IsDecompiled()) {
             DeclareFlowVariables();
             DecompileAST();
         } else {
@@ -469,18 +441,16 @@ private:
     void DecompileAST();
 
     void DecompileBranchMode() {
-        const u32 first_address = context_func->GetBasicBlocks().begin()->first;
-        const u32 func_id = context_func->GetId();
-        const std::string func_id_msg = std::to_string(func_id);
-        const Id loop_label = OpLabel("loop_" + func_id_msg);
-        const Id merge_label = OpLabel("merge_" + func_id_msg);
+        const u32 first_address = ir.GetBasicBlocks().begin()->first;
+        const Id loop_label = OpLabel("loop");
+        const Id merge_label = OpLabel("merge");
         const Id dummy_label = OpLabel();
         const Id jump_label = OpLabel();
-        continue_label = OpLabel("continue_" + func_id_msg);
+        continue_label = OpLabel("continue");
 
         std::vector<Sirit::Literal> literals;
         std::vector<Id> branch_labels;
-        for (const auto& [literal, label] : labels[func_id]) {
+        for (const auto& [literal, label] : labels) {
             literals.push_back(literal);
             branch_labels.push_back(label);
         }
@@ -492,11 +462,11 @@ private:
         std::tie(ssy_flow_stack, ssy_flow_stack_top) = CreateFlowStack();
         std::tie(pbk_flow_stack, pbk_flow_stack_top) = CreateFlowStack();
 
-        Name(jmp_to, "jmp_to_" + func_id_msg);
-        Name(ssy_flow_stack, "ssy_flow_stack_" + func_id_msg);
-        Name(ssy_flow_stack_top, "ssy_flow_stack_top_" + func_id_msg);
-        Name(pbk_flow_stack, "pbk_flow_stack_" + func_id_msg);
-        Name(pbk_flow_stack_top, "pbk_flow_stack_top_" + func_id_msg);
+        Name(jmp_to, "jmp_to");
+        Name(ssy_flow_stack, "ssy_flow_stack");
+        Name(ssy_flow_stack_top, "ssy_flow_stack_top");
+        Name(pbk_flow_stack, "pbk_flow_stack");
+        Name(pbk_flow_stack_top, "pbk_flow_stack_top");
 
         DefinePrologue();
 
@@ -514,14 +484,13 @@ private:
         AddLabel(default_branch);
         OpReturn();
 
-        for (const auto& [address, bb] : context_func->GetBasicBlocks()) {
-            AddLabel(labels[func_id].at(address));
+        for (const auto& [address, bb] : ir.GetBasicBlocks()) {
+            AddLabel(labels.at(address));
 
             VisitBasicBlock(bb);
 
-            const auto next_it = labels[func_id].lower_bound(address + 1);
-            const Id next_label =
-                next_it != labels[func_id].end() ? next_it->second : default_branch;
+            const auto next_it = labels.lower_bound(address + 1);
+            const Id next_label = next_it != labels.end() ? next_it->second : default_branch;
             OpBranch(next_label);
         }
 
@@ -539,10 +508,9 @@ private:
     static constexpr auto INTERNAL_FLAGS_COUNT = static_cast<std::size_t>(InternalFlag::Amount);
 
     void AllocateLabels() {
-        const u32 func_id = context_func->GetId();
-        for (const auto& pair : context_func->GetBasicBlocks()) {
+        for (const auto& pair : ir.GetBasicBlocks()) {
             const u32 address = pair.first;
-            labels[func_id].emplace(address, OpLabel(fmt::format("label_0x{:x}", address)));
+            labels.emplace(address, OpLabel(fmt::format("label_0x{:x}", address)));
         }
     }
 
@@ -621,14 +589,6 @@ private:
         DeclareOutputVertex();
     }
 
-    void SafeKill() {
-        if (stage != ShaderType::Fragment) {
-            OpReturn();
-            return;
-        }
-        OpKill();
-    }
-
     void DeclareFragment() {
         if (stage != ShaderType::Fragment) {
             return;
@@ -696,7 +656,7 @@ private:
     }
 
     void DeclareFlowVariables() {
-        for (u32 i = 0; i < context_func->GetASTNumVariables(); i++) {
+        for (u32 i = 0; i < ir.GetASTNumVariables(); i++) {
             const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
             Name(id, fmt::format("flow_var_{}", static_cast<u32>(i)));
             flow_variables.emplace(i, AddGlobalVariable(id));
@@ -1373,12 +1333,6 @@ private:
             return {};
         }
 
-        if (const auto func_call = std::get_if<FunctionCallNode>(&*node)) {
-            const u32 func_id = func_call->GetFuncId();
-            OpFunctionCall(t_void, other_functions[func_id - 1]);
-            return {};
-        }
-
         if (const auto comment = std::get_if<CommentNode>(&*node)) {
             if (device.HasDebuggingToolAttached()) {
                 // We should insert comments with OpString instead of using named variables
@@ -2170,7 +2124,7 @@ private:
 
         OpBranchConditional(condition, true_label, discard_label);
         AddLabel(discard_label);
-        SafeKill();
+        OpKill();
         AddLabel(true_label);
     }
 
@@ -2221,9 +2175,7 @@ private:
     }
 
     Expression Exit(Operation operation) {
-        if (context_func->IsMain()) {
-            PreExit();
-        }
+        PreExit();
         inside_branch = true;
         if (conditional_branch_set) {
             OpReturn();
@@ -2240,12 +2192,12 @@ private:
     Expression Discard(Operation operation) {
         inside_branch = true;
         if (conditional_branch_set) {
-            SafeKill();
+            OpKill();
         } else {
             const Id dummy = OpLabel();
             OpBranch(dummy);
             AddLabel(dummy);
-            SafeKill();
+            OpKill();
             AddLabel();
         }
         return {};
@@ -2324,7 +2276,7 @@ private:
     }
 
     Expression Barrier(Operation) {
-        if (!context_func->IsDecompiled()) {
+        if (!ir.IsDecompiled()) {
             LOG_ERROR(Render_Vulkan, "OpBarrier used by shader is not decompiled");
             return {};
         }
@@ -2818,8 +2770,6 @@ private:
     const Specialization& specialization;
     std::unordered_map<u8, VaryingTFB> transform_feedback;
 
-    std::shared_ptr<ShaderFunctionIR> context_func;
-
     const Id t_void = Name(TypeVoid(), "void");
 
     const Id t_bool = Name(TypeBool(), "bool");
@@ -2946,8 +2896,7 @@ private:
     Id ssy_flow_stack{};
     Id pbk_flow_stack{};
     Id continue_label{};
-    std::vector<std::map<u32, Id>> labels;
-    std::vector<Id> other_functions;
+    std::map<u32, Id> labels;
 
     bool conditional_branch_set{};
     bool inside_branch{};
@@ -3098,11 +3047,9 @@ public:
             decomp.OpBranchConditional(condition, then_label, endif_label);
             decomp.AddLabel(then_label);
             if (ast.kills) {
-                decomp.SafeKill();
+                decomp.OpKill();
             } else {
-                if (decomp.context_func->IsMain()) {
-                    decomp.PreExit();
-                }
+                decomp.PreExit();
                 decomp.OpReturn();
             }
             decomp.AddLabel(endif_label);
@@ -3111,11 +3058,9 @@ public:
             decomp.OpBranch(next_block);
             decomp.AddLabel(next_block);
             if (ast.kills) {
-                decomp.SafeKill();
+                decomp.OpKill();
             } else {
-                if (decomp.context_func->IsMain()) {
-                    decomp.PreExit();
-                }
+                decomp.PreExit();
                 decomp.OpReturn();
             }
             decomp.AddLabel(decomp.OpLabel());
@@ -3152,7 +3097,7 @@ private:
 };
 
 void SPIRVDecompiler::DecompileAST() {
-    const u32 num_flow_variables = context_func->GetASTNumVariables();
+    const u32 num_flow_variables = ir.GetASTNumVariables();
     for (u32 i = 0; i < num_flow_variables; i++) {
         const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
         Name(id, fmt::format("flow_var_{}", i));
@@ -3161,7 +3106,7 @@ void SPIRVDecompiler::DecompileAST() {
 
     DefinePrologue();
 
-    const ASTNode program = context_func->GetASTProgram();
+    const ASTNode program = ir.GetASTProgram();
     ASTDecompiler decompiler{*this};
     decompiler.Visit(program);
 
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 7c8bd7e2f..43d965f2f 100755
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -7,7 +7,6 @@
 #include <set>
 #include <stack>
 #include <unordered_map>
-#include <unordered_set>
 #include <vector>
 
 #include "common/assert.h"
@@ -27,29 +26,17 @@ using Tegra::Shader::OpCode;
 
 constexpr s32 unassigned_branch = -2;
 
-enum class JumpLabel : u32 {
-    SSYClass = 0,
-    PBKClass = 1,
-};
-
-struct JumpItem {
-    JumpLabel type;
-    u32 address;
-
-    bool operator==(const JumpItem& other) const {
-        return std::tie(type, address) == std::tie(other.type, other.address);
-    }
-};
-
 struct Query {
     u32 address{};
-    std::stack<JumpItem> stack{};
+    std::stack<u32> ssy_stack{};
+    std::stack<u32> pbk_stack{};
 };
 
 struct BlockStack {
     BlockStack() = default;
-    explicit BlockStack(const Query& q) : stack{q.stack} {}
-    std::stack<JumpItem> stack{};
+    explicit BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
+    std::stack<u32> ssy_stack{};
+    std::stack<u32> pbk_stack{};
 };
 
 template <typename T, typename... Args>
@@ -78,36 +65,20 @@ struct BlockInfo {
     }
 };
 
-struct ProgramControl {
-    std::unordered_set<u32> found_functions{};
-    std::list<u32> pending_functions{};
-
-    void RegisterFunction(u32 address) {
-        if (found_functions.count(address) != 0) {
-            return;
-        }
-        found_functions.insert(address);
-        pending_functions.emplace_back(address);
-    }
-};
-
 struct CFGRebuildState {
-    explicit CFGRebuildState(ProgramControl& control_, const ProgramCode& program_code_, u32 start_,
-                             u32 base_start_, Registry& registry_)
-        : control{control_}, program_code{program_code_}, registry{registry_}, start{start_},
-          base_start{base_start_} {}
+    explicit CFGRebuildState(const ProgramCode& program_code_, u32 start_, Registry& registry_)
+        : program_code{program_code_}, registry{registry_}, start{start_} {}
 
-    ProgramControl& control;
     const ProgramCode& program_code;
     Registry& registry;
     u32 start{};
-    u32 base_start{};
     std::vector<BlockInfo> block_info;
     std::list<u32> inspect_queries;
     std::list<Query> queries;
     std::unordered_map<u32, u32> registered;
     std::set<u32> labels;
-    std::map<u32, JumpItem> jump_labels;
+    std::map<u32, u32> ssy_labels;
+    std::map<u32, u32> pbk_labels;
     std::unordered_map<u32, BlockStack> stacks;
     ASTManager* manager{};
 };
@@ -182,7 +153,7 @@ template <typename Result, typename TestCallable, typename PackCallable>
 std::optional<Result> TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test,
                                        PackCallable pack) {
     for (; pos >= state.start; --pos) {
-        if (IsSchedInstruction(pos, state.base_start)) {
+        if (IsSchedInstruction(pos, state.start)) {
             continue;
         }
         const Instruction instr = state.program_code[pos];
@@ -291,7 +262,7 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
             single_branch.ignore = true;
             break;
         }
-        if (IsSchedInstruction(offset, state.base_start)) {
+        if (IsSchedInstruction(offset, state.start)) {
             offset++;
             continue;
         }
@@ -303,7 +274,6 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
         }
 
         switch (opcode->get().GetId()) {
-        case OpCode::Id::RET:
         case OpCode::Id::EXIT: {
             const auto pred_index = static_cast<u32>(instr.pred.pred_index);
             single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0);
@@ -441,20 +411,13 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
         case OpCode::Id::SSY: {
             const u32 target = offset + instr.bra.GetBranchTarget();
             insert_label(state, target);
-            JumpItem it = {JumpLabel::SSYClass, target};
-            state.jump_labels.emplace(offset, it);
+            state.ssy_labels.emplace(offset, target);
             break;
         }
         case OpCode::Id::PBK: {
             const u32 target = offset + instr.bra.GetBranchTarget();
             insert_label(state, target);
-            JumpItem it = {JumpLabel::PBKClass, target};
-            state.jump_labels.emplace(offset, it);
-            break;
-        }
-        case OpCode::Id::CAL: {
-            const u32 target = offset + instr.bra.GetBranchTarget();
-            state.control.RegisterFunction(target);
+            state.pbk_labels.emplace(offset, target);
             break;
         }
         case OpCode::Id::BRX: {
@@ -550,7 +513,7 @@ bool TryInspectAddress(CFGRebuildState& state) {
 }
 
 bool TryQuery(CFGRebuildState& state) {
-    const auto gather_labels = [](std::stack<JumpItem>& cc, std::map<u32, JumpItem>& labels,
+    const auto gather_labels = [](std::stack<u32>& cc, std::map<u32, u32>& labels,
                                   BlockInfo& block) {
         auto gather_start = labels.lower_bound(block.start);
         const auto gather_end = labels.upper_bound(block.end);
@@ -559,19 +522,6 @@ bool TryQuery(CFGRebuildState& state) {
             ++gather_start;
         }
     };
-    const auto pop_labels = [](JumpLabel type, SingleBranch* branch, Query& query) -> bool {
-        while (!query.stack.empty() && query.stack.top().type != type) {
-            query.stack.pop();
-        }
-        if (query.stack.empty()) {
-            return false;
-        }
-        if (branch->address == unassigned_branch) {
-            branch->address = query.stack.top().address;
-        }
-        query.stack.pop();
-        return true;
-    };
     if (state.queries.empty()) {
         return false;
     }
@@ -584,7 +534,8 @@ bool TryQuery(CFGRebuildState& state) {
     // consumes a label. Schedule new queries accordingly
     if (block.visited) {
         BlockStack& stack = state.stacks[q.address];
-        const bool all_okay = (stack.stack.empty() || q.stack == stack.stack);
+        const bool all_okay = (stack.ssy_stack.empty() || q.ssy_stack == stack.ssy_stack) &&
+                              (stack.pbk_stack.empty() || q.pbk_stack == stack.pbk_stack);
         state.queries.pop_front();
         return all_okay;
     }
@@ -593,7 +544,8 @@ bool TryQuery(CFGRebuildState& state) {
 
     Query q2(q);
     state.queries.pop_front();
-    gather_labels(q2.stack, state.jump_labels, block);
+    gather_labels(q2.ssy_stack, state.ssy_labels, block);
+    gather_labels(q2.pbk_stack, state.pbk_labels, block);
     if (std::holds_alternative<SingleBranch>(*block.branch)) {
         auto* branch = std::get_if<SingleBranch>(block.branch.get());
         if (!branch->condition.IsUnconditional()) {
@@ -603,10 +555,16 @@ bool TryQuery(CFGRebuildState& state) {
 
         auto& conditional_query = state.queries.emplace_back(q2);
         if (branch->is_sync) {
-            pop_labels(JumpLabel::SSYClass, branch, conditional_query);
+            if (branch->address == unassigned_branch) {
+                branch->address = conditional_query.ssy_stack.top();
+            }
+            conditional_query.ssy_stack.pop();
         }
         if (branch->is_brk) {
-            pop_labels(JumpLabel::PBKClass, branch, conditional_query);
+            if (branch->address == unassigned_branch) {
+                branch->address = conditional_query.pbk_stack.top();
+            }
+            conditional_query.pbk_stack.pop();
         }
         conditional_query.address = branch->address;
         return true;
@@ -688,23 +646,25 @@ void DecompileShader(CFGRebuildState& state) {
     state.manager->Decompile();
 }
 
-ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_code,
-                            u32 start_address, u32 base_start, const CompilerSettings& settings,
-                            Registry& registry) {
-    ShaderFunction result_out{};
+} // Anonymous namespace
+
+std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 start_address,
+                                                const CompilerSettings& settings,
+                                                Registry& registry) {
+    auto result_out = std::make_unique<ShaderCharacteristics>();
     if (settings.depth == CompileDepth::BruteForce) {
-        result_out.settings.depth = CompileDepth::BruteForce;
+        result_out->settings.depth = CompileDepth::BruteForce;
         return result_out;
     }
 
-    CFGRebuildState state{control, program_code, start_address, base_start, registry};
+    CFGRebuildState state{program_code, start_address, registry};
     // Inspect Code and generate blocks
     state.labels.clear();
     state.labels.emplace(start_address);
     state.inspect_queries.push_back(state.start);
     while (!state.inspect_queries.empty()) {
         if (!TryInspectAddress(state)) {
-            result_out.settings.depth = CompileDepth::BruteForce;
+            result_out->settings.depth = CompileDepth::BruteForce;
             return result_out;
         }
     }
@@ -715,7 +675,7 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_
 
     if (settings.depth != CompileDepth::FlowStack) {
         // Decompile Stacks
-        state.queries.push_back(Query{state.start, {}});
+        state.queries.push_back(Query{state.start, {}, {}});
         decompiled = true;
         while (!state.queries.empty()) {
             if (!TryQuery(state)) {
@@ -745,18 +705,19 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_
             state.manager->ShowCurrentState("Of Shader");
             state.manager->Clear();
         } else {
-            result_out.start = start_address;
-            result_out.settings.depth = settings.depth;
-            result_out.manager = std::move(manager);
-            result_out.end = state.block_info.back().end + 1;
-            return result_out;
+            auto characteristics = std::make_unique<ShaderCharacteristics>();
+            characteristics->start = start_address;
+            characteristics->settings.depth = settings.depth;
+            characteristics->manager = std::move(manager);
+            characteristics->end = state.block_info.back().end + 1;
+            return characteristics;
         }
     }
 
-    result_out.start = start_address;
-    result_out.settings.depth =
+    result_out->start = start_address;
+    result_out->settings.depth =
         use_flow_stack ? CompileDepth::FlowStack : CompileDepth::NoFlowStack;
-    result_out.blocks.clear();
+    result_out->blocks.clear();
     for (auto& block : state.block_info) {
         ShaderBlock new_block{};
         new_block.start = block.start;
@@ -765,20 +726,20 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_
         if (!new_block.ignore_branch) {
             new_block.branch = block.branch;
         }
-        result_out.end = std::max(result_out.end, block.end);
-        result_out.blocks.push_back(new_block);
+        result_out->end = std::max(result_out->end, block.end);
+        result_out->blocks.push_back(new_block);
     }
     if (!use_flow_stack) {
-        result_out.labels = std::move(state.labels);
+        result_out->labels = std::move(state.labels);
         return result_out;
     }
 
-    auto back = result_out.blocks.begin();
+    auto back = result_out->blocks.begin();
     auto next = std::next(back);
-    while (next != result_out.blocks.end()) {
+    while (next != result_out->blocks.end()) {
         if (!state.labels.contains(next->start) && next->start == back->end + 1) {
             back->end = next->end;
-            next = result_out.blocks.erase(next);
+            next = result_out->blocks.erase(next);
             continue;
         }
         back = next;
@@ -787,22 +748,4 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_
 
     return result_out;
 }
-
-} // Anonymous namespace
-
-std::unique_ptr<ShaderProgram> ScanFlow(const ProgramCode& program_code, u32 start_address,
-                                        const CompilerSettings& settings, Registry& registry) {
-    ProgramControl control{};
-    auto result_out = std::make_unique<ShaderProgram>();
-    result_out->main =
-        ScanFunction(control, program_code, start_address, start_address, settings, registry);
-    while (!control.pending_functions.empty()) {
-        u32 address = control.pending_functions.front();
-        auto fun = ScanFunction(control, program_code, address, start_address, settings, registry);
-        result_out->subfunctions.emplace(address, std::move(fun));
-        control.pending_functions.pop_front();
-    }
-    return result_out;
-}
-
 } // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h
index 5ef2251b9..37bf96492 100755
--- a/src/video_core/shader/control_flow.h
+++ b/src/video_core/shader/control_flow.h
@@ -5,7 +5,6 @@
 #pragma once
 
 #include <list>
-#include <map>
 #include <optional>
 #include <set>
 #include <variant>
@@ -102,7 +101,7 @@ struct ShaderBlock {
     }
 };
 
-struct ShaderFunction {
+struct ShaderCharacteristics {
     std::list<ShaderBlock> blocks{};
     std::set<u32> labels{};
     u32 start{};
@@ -111,12 +110,8 @@ struct ShaderFunction {
     CompilerSettings settings{};
 };
 
-struct ShaderProgram {
-    ShaderFunction main;
-    std::map<u32, ShaderFunction> subfunctions;
-};
-
-std::unique_ptr<ShaderProgram> ScanFlow(const ProgramCode& program_code, u32 start_address,
-                                        const CompilerSettings& settings, Registry& registry);
+std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 start_address,
+                                                const CompilerSettings& settings,
+                                                Registry& registry);
 
 } // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 355c724a3..6576d1208 100755
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -64,52 +64,9 @@ std::optional<u32> TryDeduceSamplerSize(const SamplerEntry& sampler_to_deduce,
 
 } // Anonymous namespace
 
-class ExprDecoder {
-public:
-    explicit ExprDecoder(ShaderIR& ir_) : ir(ir_) {}
-
-    void operator()(const ExprAnd& expr) {
-        Visit(expr.operand1);
-        Visit(expr.operand2);
-    }
-
-    void operator()(const ExprOr& expr) {
-        Visit(expr.operand1);
-        Visit(expr.operand2);
-    }
-
-    void operator()(const ExprNot& expr) {
-        Visit(expr.operand1);
-    }
-
-    void operator()(const ExprPredicate& expr) {
-        const auto pred = static_cast<Tegra::Shader::Pred>(expr.predicate);
-        if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) {
-            ir.used_predicates.insert(pred);
-        }
-    }
-
-    void operator()(const ExprCondCode& expr) {}
-
-    void operator()(const ExprVar& expr) {}
-
-    void operator()(const ExprBoolean& expr) {}
-
-    void operator()(const ExprGprEqual& expr) {
-        ir.used_registers.insert(expr.gpr);
-    }
-
-    void Visit(const Expr& node) {
-        return std::visit(*this, *node);
-    }
-
-private:
-    ShaderIR& ir;
-};
-
 class ASTDecoder {
 public:
-    explicit ASTDecoder(ShaderIR& ir_) : ir(ir_), decoder(ir_) {}
+    explicit ASTDecoder(ShaderIR& ir_) : ir(ir_) {}
 
     void operator()(ASTProgram& ast) {
         ASTNode current = ast.nodes.GetFirst();
@@ -120,7 +77,6 @@ public:
     }
 
     void operator()(ASTIfThen& ast) {
-        decoder.Visit(ast.condition);
         ASTNode current = ast.nodes.GetFirst();
         while (current) {
             Visit(current);
@@ -140,18 +96,13 @@ public:
 
     void operator()(ASTBlockDecoded& ast) {}
 
-    void operator()(ASTVarSet& ast) {
-        decoder.Visit(ast.condition);
-    }
+    void operator()(ASTVarSet& ast) {}
 
     void operator()(ASTLabel& ast) {}
 
-    void operator()(ASTGoto& ast) {
-        decoder.Visit(ast.condition);
-    }
+    void operator()(ASTGoto& ast) {}
 
     void operator()(ASTDoWhile& ast) {
-        decoder.Visit(ast.condition);
         ASTNode current = ast.nodes.GetFirst();
         while (current) {
             Visit(current);
@@ -159,13 +110,9 @@ public:
         }
     }
 
-    void operator()(ASTReturn& ast) {
-        decoder.Visit(ast.condition);
-    }
+    void operator()(ASTReturn& ast) {}
 
-    void operator()(ASTBreak& ast) {
-        decoder.Visit(ast.condition);
-    }
+    void operator()(ASTBreak& ast) {}
 
     void Visit(ASTNode& node) {
         std::visit(*this, *node->GetInnerData());
@@ -178,113 +125,77 @@ public:
 
 private:
     ShaderIR& ir;
-    ExprDecoder decoder;
 };
 
 void ShaderIR::Decode() {
-    const auto decode_function = ([this](ShaderFunction& shader_info) {
-        coverage_end = std::max<u32>(0, shader_info.end);
-        switch (shader_info.settings.depth) {
-        case CompileDepth::FlowStack: {
-            for (const auto& block : shader_info.blocks) {
-                basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)});
-            }
-            break;
-        }
-        case CompileDepth::NoFlowStack: {
-            disable_flow_stack = true;
-            const auto insert_block = [this](NodeBlock& nodes, u32 label) {
-                if (label == static_cast<u32>(exit_branch)) {
-                    return;
-                }
-                basic_blocks.insert({label, nodes});
-            };
-            const auto& blocks = shader_info.blocks;
-            NodeBlock current_block;
-            u32 current_label = static_cast<u32>(exit_branch);
-            for (const auto& block : blocks) {
-                if (shader_info.labels.contains(block.start)) {
-                    insert_block(current_block, current_label);
-                    current_block.clear();
-                    current_label = block.start;
-                }
-                if (!block.ignore_branch) {
-                    DecodeRangeInner(current_block, block.start, block.end);
-                    InsertControlFlow(current_block, block);
-                } else {
-                    DecodeRangeInner(current_block, block.start, block.end + 1);
-                }
-            }
-            insert_block(current_block, current_label);
-            break;
-        }
-        case CompileDepth::DecompileBackwards:
-        case CompileDepth::FullDecompile: {
-            program_manager = std::move(shader_info.manager);
-            disable_flow_stack = true;
-            decompiled = true;
-            ASTDecoder decoder{*this};
-            ASTNode program = program_manager.GetProgram();
-            decoder.Visit(program);
-            break;
-        }
-        default:
-            LOG_CRITICAL(HW_GPU, "Unknown decompilation mode!");
-            [[fallthrough]];
-        case CompileDepth::BruteForce: {
-            const auto shader_end = static_cast<u32>(program_code.size());
-            coverage_begin = main_offset;
-            coverage_end = shader_end;
-            for (u32 label = main_offset; label < shader_end; ++label) {
-                basic_blocks.insert({label, DecodeRange(label, label + 1)});
-            }
-            break;
-        }
-        }
-        if (settings.depth != shader_info.settings.depth) {
-            LOG_WARNING(
-                HW_GPU,
-                "Decompiling to this setting \"{}\" failed, downgrading to this setting \"{}\"",
-                CompileDepthAsString(settings.depth),
-                CompileDepthAsString(shader_info.settings.depth));
-        }
-    });
-    const auto gen_function =
-        ([this](ShaderFunction& shader_info, u32 id) -> std::shared_ptr<ShaderFunctionIR> {
-            std::shared_ptr<ShaderFunctionIR> result;
-            if (decompiled) {
-                result = std::make_shared<ShaderFunctionIR>(std::move(program_manager), id,
-                                                            shader_info.start, shader_info.end);
-            } else {
-                result =
-                    std::make_shared<ShaderFunctionIR>(std::move(basic_blocks), disable_flow_stack,
-                                                       id, shader_info.start, shader_info.end);
-            }
-            decompiled = false;
-            disable_flow_stack = false;
-            basic_blocks.clear();
-            program_manager.Clear();
-            return result;
-        });
     std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
 
     decompiled = false;
     auto info = ScanFlow(program_code, main_offset, settings, registry);
-    u32 id_start = 1;
-    for (auto& pair : info->subfunctions) {
-        func_map.emplace(pair.first, id_start);
-        id_start++;
+    auto& shader_info = *info;
+    coverage_begin = shader_info.start;
+    coverage_end = shader_info.end;
+    switch (shader_info.settings.depth) {
+    case CompileDepth::FlowStack: {
+        for (const auto& block : shader_info.blocks) {
+            basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)});
+        }
+        break;
     }
-    coverage_begin = info->main.start;
-    coverage_end = 0;
-    decode_function(info->main);
-    main_function = gen_function(info->main, 0);
-    subfunctions.resize(info->subfunctions.size());
-    for (auto& pair : info->subfunctions) {
-        auto& func_info = pair.second;
-        decode_function(func_info);
-        u32 id = func_map[pair.first];
-        subfunctions[id - 1] = gen_function(func_info, id);
+    case CompileDepth::NoFlowStack: {
+        disable_flow_stack = true;
+        const auto insert_block = [this](NodeBlock& nodes, u32 label) {
+            if (label == static_cast<u32>(exit_branch)) {
+                return;
+            }
+            basic_blocks.insert({label, nodes});
+        };
+        const auto& blocks = shader_info.blocks;
+        NodeBlock current_block;
+        u32 current_label = static_cast<u32>(exit_branch);
+        for (const auto& block : blocks) {
+            if (shader_info.labels.contains(block.start)) {
+                insert_block(current_block, current_label);
+                current_block.clear();
+                current_label = block.start;
+            }
+            if (!block.ignore_branch) {
+                DecodeRangeInner(current_block, block.start, block.end);
+                InsertControlFlow(current_block, block);
+            } else {
+                DecodeRangeInner(current_block, block.start, block.end + 1);
+            }
+        }
+        insert_block(current_block, current_label);
+        break;
+    }
+    case CompileDepth::DecompileBackwards:
+    case CompileDepth::FullDecompile: {
+        program_manager = std::move(shader_info.manager);
+        disable_flow_stack = true;
+        decompiled = true;
+        ASTDecoder decoder{*this};
+        ASTNode program = GetASTProgram();
+        decoder.Visit(program);
+        break;
+    }
+    default:
+        LOG_CRITICAL(HW_GPU, "Unknown decompilation mode!");
+        [[fallthrough]];
+    case CompileDepth::BruteForce: {
+        const auto shader_end = static_cast<u32>(program_code.size());
+        coverage_begin = main_offset;
+        coverage_end = shader_end;
+        for (u32 label = main_offset; label < shader_end; ++label) {
+            basic_blocks.insert({label, DecodeRange(label, label + 1)});
+        }
+        break;
+    }
+    }
+    if (settings.depth != shader_info.settings.depth) {
+        LOG_WARNING(
+            HW_GPU, "Decompiling to this setting \"{}\" failed, downgrading to this setting \"{}\"",
+            CompileDepthAsString(settings.depth), CompileDepthAsString(shader_info.settings.depth));
     }
 }
 
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index 2bc596512..5f88537bc 100755
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -33,7 +33,6 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
         // With the previous preconditions, this instruction is a no-operation.
         break;
     }
-    case OpCode::Id::RET:
     case OpCode::Id::EXIT: {
         const ConditionCode cc = instr.flow_condition_code;
         UNIMPLEMENTED_IF_MSG(cc != ConditionCode::T, "EXIT condition code used: {}", cc);
@@ -313,16 +312,6 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
         LOG_DEBUG(HW_GPU, "DEPBAR instruction is stubbed");
         break;
     }
-    case OpCode::Id::CAL: {
-        const u32 target = pc + instr.bra.GetBranchTarget();
-        const auto it = func_map.find(target);
-        if (it == func_map.end()) {
-            UNREACHABLE();
-            break;
-        }
-        bb.push_back(FunctionCall(it->second));
-        break;
-    }
     default:
         UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName());
     }
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 43a166b6f..c69681e8d 100755
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -339,6 +339,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
         const TextureType texture_type{instr.tlds.GetTextureType()};
         const bool is_array{instr.tlds.IsArrayTexture()};
 
+        UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI),
+                             "AOFFI is not implemented");
         UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented");
 
         const Node4 components = GetTldsCode(instr, texture_type, is_array);
@@ -820,7 +822,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
     for (std::size_t i = 0; i < type_coord_count; ++i) {
         const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1);
         coords.push_back(
-            GetRegister(last && !aoffi_enabled ? last_coord_register : (coord_register + i)));
+            GetRegister(last && !aoffi_enabled ? last_coord_register : coord_register + i));
     }
 
     const Node array = is_array ? GetRegister(array_register) : nullptr;
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index a58e7c65e..b54d33763 100755
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -267,11 +267,10 @@ class PatchNode;
 class SmemNode;
 class GmemNode;
 class CommentNode;
-class FunctionCallNode;
 
 using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, CustomVarNode, ImmediateNode,
                               InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode,
-                              LmemNode, SmemNode, GmemNode, FunctionCallNode, CommentNode>;
+                              LmemNode, SmemNode, GmemNode, CommentNode>;
 using Node = std::shared_ptr<NodeData>;
 using Node4 = std::array<Node, 4>;
 using NodeBlock = std::vector<Node>;
@@ -495,18 +494,6 @@ private:
     std::vector<Node> code; ///< Code to execute
 };
 
-class FunctionCallNode final : public AmendNode {
-public:
-    explicit FunctionCallNode(u32 func_id_) : func_id{func_id_} {}
-
-    [[nodiscard]] u32 GetFuncId() const {
-        return func_id;
-    }
-
-private:
-    u32 func_id; ///< Id of the function to call
-};
-
 /// A general purpose register
 class GprNode final {
 public:
diff --git a/src/video_core/shader/node_helper.cpp b/src/video_core/shader/node_helper.cpp
index cef9c26bc..6a5b6940d 100755
--- a/src/video_core/shader/node_helper.cpp
+++ b/src/video_core/shader/node_helper.cpp
@@ -19,11 +19,6 @@ Node Comment(std::string text) {
     return MakeNode<CommentNode>(std::move(text));
 }
 
-/// Creates a function call
-Node FunctionCall(u32 func_id) {
-    return MakeNode<FunctionCallNode>(func_id);
-}
-
 Node Immediate(u32 value) {
     return MakeNode<ImmediateNode>(value);
 }
diff --git a/src/video_core/shader/node_helper.h b/src/video_core/shader/node_helper.h
index 3f882cd25..1e0886185 100755
--- a/src/video_core/shader/node_helper.h
+++ b/src/video_core/shader/node_helper.h
@@ -27,9 +27,6 @@ Node Conditional(Node condition, std::vector<Node> code);
 /// Creates a commentary node
 Node Comment(std::string text);
 
-/// Creates a function call
-Node FunctionCall(u32 func_id);
-
 /// Creates an u32 immediate
 Node Immediate(u32 value);
 
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 94715b069..1cd7c14d7 100755
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -26,7 +26,7 @@ namespace VideoCommon::Shader {
 
 struct ShaderBlock;
 
-constexpr u32 MAX_PROGRAM_LENGTH = 0x2000;
+constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
 
 struct ConstBuffer {
     constexpr explicit ConstBuffer(u32 max_offset_, bool is_indirect_)
@@ -64,68 +64,16 @@ struct GlobalMemoryUsage {
     bool is_written{};
 };
 
-class ShaderFunctionIR final {
-public:
-    explicit ShaderFunctionIR(std::map<u32, NodeBlock>&& basic_blocks_, bool disable_flow_stack_,
-                              u32 id_, u32 coverage_begin_, u32 coverage_end_)
-        : basic_blocks{std::move(basic_blocks_)}, decompiled{false},
-          disable_flow_stack{disable_flow_stack_}, id{id_}, coverage_begin{coverage_begin_},
-          coverage_end{coverage_end_} {}
-    explicit ShaderFunctionIR(ASTManager&& program_manager_, u32 id_, u32 coverage_begin_,
-                              u32 coverage_end_)
-        : program_manager{std::move(program_manager_)}, decompiled{true}, disable_flow_stack{true},
-          id{id_}, coverage_begin{coverage_begin_}, coverage_end{coverage_end_} {}
-
-    const std::map<u32, NodeBlock>& GetBasicBlocks() const {
-        return basic_blocks;
-    }
-
-    [[nodiscard]] bool IsFlowStackDisabled() const {
-        return disable_flow_stack;
-    }
-
-    [[nodiscard]] bool IsDecompiled() const {
-        return decompiled;
-    }
-
-    const ASTManager& GetASTManager() const {
-        return program_manager;
-    }
-
-    [[nodiscard]] ASTNode GetASTProgram() const {
-        return program_manager.GetProgram();
-    }
-
-    [[nodiscard]] u32 GetASTNumVariables() const {
-        return program_manager.GetVariables();
-    }
-
-    [[nodiscard]] bool IsMain() const {
-        return id == 0;
-    }
-
-    [[nodiscard]] u32 GetId() const {
-        return id;
-    }
-
-private:
-    std::map<u32, NodeBlock> basic_blocks;
-    ASTManager program_manager{true, true};
-
-    bool decompiled{};
-    bool disable_flow_stack{};
-    u32 id{};
-
-    u32 coverage_begin{};
-    u32 coverage_end{};
-};
-
 class ShaderIR final {
 public:
     explicit ShaderIR(const ProgramCode& program_code_, u32 main_offset_,
                       CompilerSettings settings_, Registry& registry_);
     ~ShaderIR();
 
+    const std::map<u32, NodeBlock>& GetBasicBlocks() const {
+        return basic_blocks;
+    }
+
     const std::set<u32>& GetRegisters() const {
         return used_registers;
     }
@@ -207,6 +155,26 @@ public:
         return header;
     }
 
+    bool IsFlowStackDisabled() const {
+        return disable_flow_stack;
+    }
+
+    bool IsDecompiled() const {
+        return decompiled;
+    }
+
+    const ASTManager& GetASTManager() const {
+        return program_manager;
+    }
+
+    ASTNode GetASTProgram() const {
+        return program_manager.GetProgram();
+    }
+
+    u32 GetASTNumVariables() const {
+        return program_manager.GetVariables();
+    }
+
     u32 ConvertAddressToNvidiaSpace(u32 address) const {
         return (address - main_offset) * static_cast<u32>(sizeof(Tegra::Shader::Instruction));
     }
@@ -222,16 +190,7 @@ public:
         return num_custom_variables;
     }
 
-    std::shared_ptr<ShaderFunctionIR> GetMainFunction() const {
-        return main_function;
-    }
-
-    const std::vector<std::shared_ptr<ShaderFunctionIR>>& GetSubFunctions() const {
-        return subfunctions;
-    }
-
 private:
-    friend class ExprDecoder;
     friend class ASTDecoder;
 
     struct SamplerInfo {
@@ -494,10 +453,6 @@ private:
     std::vector<Node> amend_code;
     u32 num_custom_variables{};
 
-    std::shared_ptr<ShaderFunctionIR> main_function;
-    std::vector<std::shared_ptr<ShaderFunctionIR>> subfunctions;
-    std::unordered_map<u32, u32> func_map;
-
     std::set<u32> used_registers;
     std::set<Tegra::Shader::Pred> used_predicates;
     std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index cc0790e07..b025ced1c 100755
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -18,7 +18,6 @@ add_executable(yuzu
     applets/profile_select.h
     applets/software_keyboard.cpp
     applets/software_keyboard.h
-    applets/software_keyboard.ui
     applets/web_browser.cpp
     applets/web_browser.h
     bootmanager.cpp
@@ -144,9 +143,6 @@ add_executable(yuzu
     uisettings.h
     util/limitable_input_dialog.cpp
     util/limitable_input_dialog.h
-    util/overlay_dialog.cpp
-    util/overlay_dialog.h
-    util/overlay_dialog.ui
     util/sequence_dialog/sequence_dialog.cpp
     util/sequence_dialog/sequence_dialog.h
     util/url_request_interceptor.cpp
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
index 085688cd4..8ee03ddb3 100755
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/error.cpp
@@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default;
 void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const {
     callback = std::move(finished);
     emit MainWindowDisplayError(
-        tr("Error Code: %1-%2 (0x%3)")
+        tr("An error has occurred.\nPlease try again or contact the developer of the "
+           "software.\n\nError Code: %1-%2 (0x%3)")
             .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
             .arg(error.description, 4, 10, QChar::fromLatin1('0'))
-            .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
-        tr("An error has occurred.\nPlease try again or contact the developer of the software."));
+            .arg(error.raw, 8, 16, QChar::fromLatin1('0')));
 }
 
 void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
@@ -32,14 +32,13 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon
 
     const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
     emit MainWindowDisplayError(
-        tr("Error Code: %1-%2 (0x%3)")
+        tr("An error occurred on %1 at %2.\nPlease try again or contact the "
+           "developer of the software.\n\nError Code: %3-%4 (0x%5)")
+            .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
+            .arg(date_time.toString(QStringLiteral("h:mm:ss A")))
             .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
             .arg(error.description, 4, 10, QChar::fromLatin1('0'))
-            .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
-        tr("An error occurred on %1 at %2.\nPlease try again or contact the developer of the "
-           "software.")
-            .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
-            .arg(date_time.toString(QStringLiteral("h:mm:ss A"))));
+            .arg(error.raw, 8, 16, QChar::fromLatin1('0')));
 }
 
 void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text,
@@ -47,11 +46,10 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
                                          std::function<void()> finished) const {
     callback = std::move(finished);
     emit MainWindowDisplayError(
-        tr("Error Code: %1-%2 (0x%3)")
+        tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5")
             .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
             .arg(error.description, 4, 10, QChar::fromLatin1('0'))
-            .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
-        tr("An error has occurred.\n\n%1\n\n%2")
+            .arg(error.raw, 8, 16, QChar::fromLatin1('0'))
             .arg(QString::fromStdString(dialog_text))
             .arg(QString::fromStdString(fullscreen_text)));
 }
diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h
index 8bd895a32..b0932d895 100755
--- a/src/yuzu/applets/error.h
+++ b/src/yuzu/applets/error.h
@@ -24,7 +24,7 @@ public:
                              std::function<void()> finished) const override;
 
 signals:
-    void MainWindowDisplayError(QString error_code, QString error_text) const;
+    void MainWindowDisplayError(QString error) const;
 
 private:
     void MainWindowFinishedError();
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp
index 06bab08d4..ab8cfd8ee 100755
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/software_keyboard.cpp
@@ -1,1641 +1,153 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu Emulator Project
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <QCursor>
-#include <QKeyEvent>
-#include <QScreen>
-
-#include "common/logging/log.h"
-#include "common/string_util.h"
-#include "core/core.h"
-#include "core/frontend/input_interpreter.h"
-#include "core/settings.h"
-#include "ui_software_keyboard.h"
+#include <algorithm>
+#include <mutex>
+#include <QDialogButtonBox>
+#include <QFont>
+#include <QLabel>
+#include <QLineEdit>
+#include <QVBoxLayout>
+#include "core/hle/lock.h"
 #include "yuzu/applets/software_keyboard.h"
 #include "yuzu/main.h"
-#include "yuzu/util/overlay_dialog.h"
 
-namespace {
+QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
+    Core::Frontend::SoftwareKeyboardParameters parameters)
+    : parameters(std::move(parameters)) {}
 
-using namespace Service::AM::Applets;
+QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
+    if (input.size() > static_cast<s64>(parameters.max_length)) {
+        return Invalid;
+    }
+    if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
+        return Invalid;
+    }
+    if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
+        return Invalid;
+    }
+    if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
+        return Invalid;
+    }
+    if (parameters.disable_slash &&
+        (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
+        return Invalid;
+    }
+    if (parameters.disable_number &&
+        std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
+        return Invalid;
+    }
 
-constexpr float BASE_HEADER_FONT_SIZE = 23.0f;
-constexpr float BASE_SUB_FONT_SIZE = 17.0f;
-constexpr float BASE_EDITOR_FONT_SIZE = 26.0f;
-constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f;
-constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f;
-constexpr float BASE_ICON_BUTTON_SIZE = 36.0f;
-[[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f;
-constexpr float BASE_HEIGHT = 720.0f;
+    if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
+            return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
+        })) {
+        return Invalid;
+    }
 
-} // Anonymous namespace
+    return Acceptable;
+}
 
 QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
-    QWidget* parent, Core::System& system_, bool is_inline_,
-    Core::Frontend::KeyboardInitializeParameters initialize_parameters_)
-    : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_},
-      is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} {
-    ui->setupUi(this);
+    QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
+    : QDialog(parent), parameters(std::move(parameters_)) {
+    layout = new QVBoxLayout;
 
-    setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
-                   Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
-    setWindowModality(Qt::WindowModal);
-    setAttribute(Qt::WA_DeleteOnClose);
-    setAttribute(Qt::WA_TranslucentBackground);
+    header_label = new QLabel(QString::fromStdU16String(parameters.header_text));
+    header_label->setFont({header_label->font().family(), 11, QFont::Bold});
+    if (header_label->text().isEmpty())
+        header_label->setText(tr("Enter text:"));
 
-    keyboard_buttons = {{
-        {{
-            {
-                ui->button_1,
-                ui->button_2,
-                ui->button_3,
-                ui->button_4,
-                ui->button_5,
-                ui->button_6,
-                ui->button_7,
-                ui->button_8,
-                ui->button_9,
-                ui->button_0,
-                ui->button_minus,
-                ui->button_backspace,
-            },
-            {
-                ui->button_q,
-                ui->button_w,
-                ui->button_e,
-                ui->button_r,
-                ui->button_t,
-                ui->button_y,
-                ui->button_u,
-                ui->button_i,
-                ui->button_o,
-                ui->button_p,
-                ui->button_slash,
-                ui->button_return,
-            },
-            {
-                ui->button_a,
-                ui->button_s,
-                ui->button_d,
-                ui->button_f,
-                ui->button_g,
-                ui->button_h,
-                ui->button_j,
-                ui->button_k,
-                ui->button_l,
-                ui->button_colon,
-                ui->button_apostrophe,
-                ui->button_return,
-            },
-            {
-                ui->button_z,
-                ui->button_x,
-                ui->button_c,
-                ui->button_v,
-                ui->button_b,
-                ui->button_n,
-                ui->button_m,
-                ui->button_comma,
-                ui->button_dot,
-                ui->button_question,
-                ui->button_exclamation,
-                ui->button_ok,
-            },
-            {
-                ui->button_shift,
-                ui->button_shift,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_space,
-                ui->button_ok,
-            },
-        }},
-        {{
-            {
-                ui->button_hash,
-                ui->button_left_bracket,
-                ui->button_right_bracket,
-                ui->button_dollar,
-                ui->button_percent,
-                ui->button_circumflex,
-                ui->button_ampersand,
-                ui->button_asterisk,
-                ui->button_left_parenthesis,
-                ui->button_right_parenthesis,
-                ui->button_underscore,
-                ui->button_backspace_shift,
-            },
-            {
-                ui->button_q_shift,
-                ui->button_w_shift,
-                ui->button_e_shift,
-                ui->button_r_shift,
-                ui->button_t_shift,
-                ui->button_y_shift,
-                ui->button_u_shift,
-                ui->button_i_shift,
-                ui->button_o_shift,
-                ui->button_p_shift,
-                ui->button_at,
-                ui->button_return_shift,
-            },
-            {
-                ui->button_a_shift,
-                ui->button_s_shift,
-                ui->button_d_shift,
-                ui->button_f_shift,
-                ui->button_g_shift,
-                ui->button_h_shift,
-                ui->button_j_shift,
-                ui->button_k_shift,
-                ui->button_l_shift,
-                ui->button_semicolon,
-                ui->button_quotation,
-                ui->button_return_shift,
-            },
-            {
-                ui->button_z_shift,
-                ui->button_x_shift,
-                ui->button_c_shift,
-                ui->button_v_shift,
-                ui->button_b_shift,
-                ui->button_n_shift,
-                ui->button_m_shift,
-                ui->button_less_than,
-                ui->button_greater_than,
-                ui->button_plus,
-                ui->button_equal,
-                ui->button_ok_shift,
-            },
-            {
-                ui->button_shift_shift,
-                ui->button_shift_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_space_shift,
-                ui->button_ok_shift,
-            },
-        }},
-    }};
+    sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text));
+    sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(),
+                        sub_label->font().weight(), true});
+    sub_label->setHidden(parameters.sub_text.empty());
 
-    numberpad_buttons = {{
-        {
-            ui->button_1_num,
-            ui->button_2_num,
-            ui->button_3_num,
-            ui->button_backspace_num,
-        },
-        {
-            ui->button_4_num,
-            ui->button_5_num,
-            ui->button_6_num,
-            ui->button_ok_num,
-        },
-        {
-            ui->button_7_num,
-            ui->button_8_num,
-            ui->button_9_num,
-            ui->button_ok_num,
-        },
-        {
-            nullptr,
-            ui->button_0_num,
-            nullptr,
-            ui->button_ok_num,
-        },
-    }};
+    guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text));
+    guide_label->setHidden(parameters.guide_text.empty());
 
-    all_buttons = {
-        ui->button_1,
-        ui->button_2,
-        ui->button_3,
-        ui->button_4,
-        ui->button_5,
-        ui->button_6,
-        ui->button_7,
-        ui->button_8,
-        ui->button_9,
-        ui->button_0,
-        ui->button_minus,
-        ui->button_backspace,
-        ui->button_q,
-        ui->button_w,
-        ui->button_e,
-        ui->button_r,
-        ui->button_t,
-        ui->button_y,
-        ui->button_u,
-        ui->button_i,
-        ui->button_o,
-        ui->button_p,
-        ui->button_slash,
-        ui->button_return,
-        ui->button_a,
-        ui->button_s,
-        ui->button_d,
-        ui->button_f,
-        ui->button_g,
-        ui->button_h,
-        ui->button_j,
-        ui->button_k,
-        ui->button_l,
-        ui->button_colon,
-        ui->button_apostrophe,
-        ui->button_z,
-        ui->button_x,
-        ui->button_c,
-        ui->button_v,
-        ui->button_b,
-        ui->button_n,
-        ui->button_m,
-        ui->button_comma,
-        ui->button_dot,
-        ui->button_question,
-        ui->button_exclamation,
-        ui->button_ok,
-        ui->button_shift,
-        ui->button_space,
-        ui->button_hash,
-        ui->button_left_bracket,
-        ui->button_right_bracket,
-        ui->button_dollar,
-        ui->button_percent,
-        ui->button_circumflex,
-        ui->button_ampersand,
-        ui->button_asterisk,
-        ui->button_left_parenthesis,
-        ui->button_right_parenthesis,
-        ui->button_underscore,
-        ui->button_backspace_shift,
-        ui->button_q_shift,
-        ui->button_w_shift,
-        ui->button_e_shift,
-        ui->button_r_shift,
-        ui->button_t_shift,
-        ui->button_y_shift,
-        ui->button_u_shift,
-        ui->button_i_shift,
-        ui->button_o_shift,
-        ui->button_p_shift,
-        ui->button_at,
-        ui->button_return_shift,
-        ui->button_a_shift,
-        ui->button_s_shift,
-        ui->button_d_shift,
-        ui->button_f_shift,
-        ui->button_g_shift,
-        ui->button_h_shift,
-        ui->button_j_shift,
-        ui->button_k_shift,
-        ui->button_l_shift,
-        ui->button_semicolon,
-        ui->button_quotation,
-        ui->button_z_shift,
-        ui->button_x_shift,
-        ui->button_c_shift,
-        ui->button_v_shift,
-        ui->button_b_shift,
-        ui->button_n_shift,
-        ui->button_m_shift,
-        ui->button_less_than,
-        ui->button_greater_than,
-        ui->button_plus,
-        ui->button_equal,
-        ui->button_ok_shift,
-        ui->button_shift_shift,
-        ui->button_space_shift,
-        ui->button_1_num,
-        ui->button_2_num,
-        ui->button_3_num,
-        ui->button_backspace_num,
-        ui->button_4_num,
-        ui->button_5_num,
-        ui->button_6_num,
-        ui->button_ok_num,
-        ui->button_7_num,
-        ui->button_8_num,
-        ui->button_9_num,
-        ui->button_0_num,
-    };
+    length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length));
+    length_label->setAlignment(Qt::AlignRight);
+    length_label->setFont({length_label->font().family(), 8});
 
-    SetupMouseHover();
+    line_edit = new QLineEdit;
+    line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters));
+    line_edit->setMaxLength(static_cast<int>(parameters.max_length));
+    line_edit->setText(QString::fromStdU16String(parameters.initial_text));
+    line_edit->setCursorPosition(
+        parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size()));
+    line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal);
 
-    if (!initialize_parameters.ok_text.empty()) {
-        ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text));
-    }
-
-    ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text));
-    ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text));
-
-    current_text = initialize_parameters.initial_text;
-    cursor_position = initialize_parameters.initial_cursor_position;
-
-    SetTextDrawType();
-
-    for (auto* button : all_buttons) {
-        connect(button, &QPushButton::clicked, this, [this, button](bool) {
-            if (is_inline) {
-                InlineKeyboardButtonClicked(button);
-            } else {
-                NormalKeyboardButtonClicked(button);
-            }
-        });
-    }
-
-    // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
-    if (system.IsPoweredOn()) {
-        input_interpreter = std::make_unique<InputInterpreter>(system);
+    connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) {
+        length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length));
+    });
+
+    buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
+    if (parameters.submit_text.empty()) {
+        buttons->addButton(QDialogButtonBox::Ok);
+    } else {
+        buttons->addButton(QString::fromStdU16String(parameters.submit_text),
+                           QDialogButtonBox::AcceptRole);
     }
+    connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept);
+    connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject);
+    layout->addWidget(header_label);
+    layout->addWidget(sub_label);
+    layout->addWidget(guide_label);
+    layout->addWidget(length_label);
+    layout->addWidget(line_edit);
+    layout->addWidget(buttons);
+    setLayout(layout);
+    setWindowTitle(tr("Software Keyboard"));
 }
 
-QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() {
-    StopInputThread();
-}
+QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default;
 
-void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) {
-    if (isVisible()) {
-        return;
-    }
-
-    MoveAndResizeWindow(pos, size);
-
-    SetKeyboardType();
-    SetPasswordMode();
-    SetControllerImage();
-    DisableKeyboardButtons();
-    SetBackspaceOkEnabled();
-
-    open();
-}
-
-void QtSoftwareKeyboardDialog::ShowTextCheckDialog(
-    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-    std::u16string text_check_message) {
-    switch (text_check_result) {
-    case SwkbdTextCheckResult::Success:
-    case SwkbdTextCheckResult::Silent:
-    default:
-        break;
-    case SwkbdTextCheckResult::Failure: {
-        StopInputThread();
-
-        OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
-                             QString{}, tr("OK"), Qt::AlignCenter);
-        dialog.exec();
-
-        StartInputThread();
-        break;
-    }
-    case SwkbdTextCheckResult::Confirm: {
-        StopInputThread();
-
-        OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
-                             tr("Cancel"), tr("OK"), Qt::AlignCenter);
-        if (dialog.exec() == QDialog::Accepted) {
-            emit SubmitNormalText(SwkbdResult::Ok, current_text);
-            break;
-        }
-
-        StartInputThread();
-        break;
-    }
-    }
-}
-
-void QtSoftwareKeyboardDialog::ShowInlineKeyboard(
-    Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) {
-    MoveAndResizeWindow(pos, size);
-
-    ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);"));
-
-    ui->headerOSK->hide();
-    ui->subOSK->hide();
-    ui->inputOSK->hide();
-    ui->charactersOSK->hide();
-    ui->inputBoxOSK->hide();
-    ui->charactersBoxOSK->hide();
-
-    initialize_parameters.max_text_length = appear_parameters.max_text_length;
-    initialize_parameters.min_text_length = appear_parameters.min_text_length;
-    initialize_parameters.type = appear_parameters.type;
-    initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags;
-    initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button;
-    initialize_parameters.enable_return_button = appear_parameters.enable_return_button;
-    initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button;
-
-    SetKeyboardType();
-    SetControllerImage();
-    DisableKeyboardButtons();
-    SetBackspaceOkEnabled();
-
-    open();
-}
-
-void QtSoftwareKeyboardDialog::HideInlineKeyboard() {
-    StopInputThread();
-    QDialog::hide();
-}
-
-void QtSoftwareKeyboardDialog::InlineTextChanged(
-    Core::Frontend::InlineTextParameters text_parameters) {
-    current_text = text_parameters.input_text;
-    cursor_position = text_parameters.cursor_position;
-
-    SetBackspaceOkEnabled();
-}
-
-void QtSoftwareKeyboardDialog::ExitKeyboard() {
-    StopInputThread();
-    QDialog::done(QDialog::Accepted);
-}
-
-void QtSoftwareKeyboardDialog::open() {
-    QDialog::open();
-
-    row = 0;
-    column = 0;
-
-    const auto* const curr_button =
-        keyboard_buttons[static_cast<int>(bottom_osk_index)][row][column];
-
-    // This is a workaround for setFocus() randomly not showing focus in the UI
-    QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
-
-    StartInputThread();
+void QtSoftwareKeyboardDialog::accept() {
+    text = line_edit->text().toStdU16String();
+    QDialog::accept();
 }
 
 void QtSoftwareKeyboardDialog::reject() {
-    // Pressing the ESC key in a dialog calls QDialog::reject().
-    // We will override this behavior to the "Cancel" action on the software keyboard.
-    if (is_inline) {
-        emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
-    } else {
-        emit SubmitNormalText(SwkbdResult::Cancel, current_text);
-    }
+    text.clear();
+    QDialog::reject();
 }
 
-void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
-    if (!is_inline) {
-        QDialog::keyPressEvent(event);
-        return;
-    }
-
-    const auto entered_key = event->key();
-
-    switch (entered_key) {
-    case Qt::Key_Escape:
-        QDialog::keyPressEvent(event);
-        return;
-    case Qt::Key_Backspace:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_backspace->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_backspace_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-            ui->button_backspace_num->click();
-            break;
-        default:
-            break;
-        }
-        return;
-    case Qt::Key_Return:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_ok->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_ok_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-            ui->button_ok_num->click();
-            break;
-        default:
-            break;
-        }
-        return;
-    case Qt::Key_Left:
-        MoveTextCursorDirection(Direction::Left);
-        return;
-    case Qt::Key_Right:
-        MoveTextCursorDirection(Direction::Right);
-        return;
-    default:
-        break;
-    }
-
-    const auto entered_text = event->text();
-
-    if (entered_text.isEmpty()) {
-        return;
-    }
-
-    InlineTextInsertString(entered_text.toStdU16String());
-}
-
-void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) {
-    QDialog::move(pos);
-    QDialog::resize(size);
-
-    // High DPI
-    const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
-
-    RescaleKeyboardElements(size.width(), size.height(), dpi_scale);
-}
-
-void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) {
-    const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
-    const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
-    const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
-    const auto char_button_font_size =
-        BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
-    const auto label_button_font_size =
-        BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
-
-    QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal);
-    QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal);
-    QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal);
-    QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal);
-    QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size,
-                            QFont::Normal);
-
-    ui->label_header->setFont(header_font);
-    ui->label_sub->setFont(sub_font);
-    ui->line_edit_osk->setFont(editor_font);
-    ui->text_edit_osk->setFont(editor_font);
-    ui->label_characters->setFont(sub_font);
-    ui->label_characters_box->setFont(sub_font);
-
-    ui->label_shift->setFont(label_button_font);
-    ui->label_shift_shift->setFont(label_button_font);
-    ui->label_cancel->setFont(label_button_font);
-    ui->label_cancel_shift->setFont(label_button_font);
-    ui->label_cancel_num->setFont(label_button_font);
-    ui->label_enter->setFont(label_button_font);
-    ui->label_enter_shift->setFont(label_button_font);
-    ui->label_enter_num->setFont(label_button_font);
-
-    for (auto* button : all_buttons) {
-        if (button == ui->button_return || button == ui->button_return_shift) {
-            button->setFont(label_button_font);
-            continue;
-        }
-
-        if (button == ui->button_space || button == ui->button_space_shift) {
-            button->setFont(label_button_font);
-            continue;
-        }
-
-        if (button == ui->button_shift || button == ui->button_shift_shift) {
-            button->setFont(label_button_font);
-            button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
-                                (height / BASE_HEIGHT));
-            continue;
-        }
-
-        if (button == ui->button_backspace || button == ui->button_backspace_shift ||
-            button == ui->button_backspace_num) {
-            button->setFont(label_button_font);
-            button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
-                                (height / BASE_HEIGHT));
-            continue;
-        }
-
-        if (button == ui->button_ok || button == ui->button_ok_shift ||
-            button == ui->button_ok_num) {
-            button->setFont(label_button_font);
-            continue;
-        }
-
-        button->setFont(char_button_font);
-    }
-}
-
-void QtSoftwareKeyboardDialog::SetKeyboardType() {
-    switch (initialize_parameters.type) {
-    case SwkbdType::Normal:
-    case SwkbdType::Qwerty:
-    case SwkbdType::Unknown3:
-    case SwkbdType::Latin:
-    case SwkbdType::SimplifiedChinese:
-    case SwkbdType::TraditionalChinese:
-    case SwkbdType::Korean:
-    default: {
-        bottom_osk_index = BottomOSKIndex::LowerCase;
-        ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
-
-        ui->verticalLayout_2->setStretch(0, 320);
-        ui->verticalLayout_2->setStretch(1, 400);
-
-        ui->gridLineOSK->setRowStretch(5, 94);
-        ui->gridBoxOSK->setRowStretch(2, 81);
-        break;
-    }
-    case SwkbdType::NumberPad: {
-        bottom_osk_index = BottomOSKIndex::NumberPad;
-        ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
-
-        ui->verticalLayout_2->setStretch(0, 370);
-        ui->verticalLayout_2->setStretch(1, 350);
-
-        ui->gridLineOSK->setRowStretch(5, 144);
-        ui->gridBoxOSK->setRowStretch(2, 131);
-        break;
-    }
-    }
-}
-
-void QtSoftwareKeyboardDialog::SetPasswordMode() {
-    switch (initialize_parameters.password_mode) {
-    case SwkbdPasswordMode::Disabled:
-    default:
-        ui->line_edit_osk->setEchoMode(QLineEdit::Normal);
-        break;
-    case SwkbdPasswordMode::Enabled:
-        ui->line_edit_osk->setEchoMode(QLineEdit::Password);
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::SetTextDrawType() {
-    switch (initialize_parameters.text_draw_type) {
-    case SwkbdTextDrawType::Line:
-    case SwkbdTextDrawType::DownloadCode: {
-        ui->topOSK->setCurrentIndex(0);
-
-        if (initialize_parameters.max_text_length <= 10) {
-            ui->gridLineOSK->setColumnStretch(0, 390);
-            ui->gridLineOSK->setColumnStretch(1, 500);
-            ui->gridLineOSK->setColumnStretch(2, 390);
-        } else {
-            ui->gridLineOSK->setColumnStretch(0, 130);
-            ui->gridLineOSK->setColumnStretch(1, 1020);
-            ui->gridLineOSK->setColumnStretch(2, 130);
-        }
-
-        if (is_inline) {
-            return;
-        }
-
-        connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) {
-            const auto is_valid = ValidateInputText(changed_string);
-
-            const auto text_length = static_cast<u32>(changed_string.length());
-
-            ui->label_characters->setText(QStringLiteral("%1/%2")
-                                              .arg(text_length)
-                                              .arg(initialize_parameters.max_text_length));
-
-            ui->button_ok->setEnabled(is_valid);
-            ui->button_ok_shift->setEnabled(is_valid);
-            ui->button_ok_num->setEnabled(is_valid);
-
-            ui->line_edit_osk->setFocus();
-        });
-
-        connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged,
-                [this](int old_cursor_position, int new_cursor_position) {
-                    ui->button_backspace->setEnabled(
-                        initialize_parameters.enable_backspace_button && new_cursor_position > 0);
-                    ui->button_backspace_shift->setEnabled(
-                        initialize_parameters.enable_backspace_button && new_cursor_position > 0);
-                    ui->button_backspace_num->setEnabled(
-                        initialize_parameters.enable_backspace_button && new_cursor_position > 0);
-
-                    ui->line_edit_osk->setFocus();
-                });
-
-        connect(ui->line_edit_osk, &QLineEdit::returnPressed, [this] {
-            switch (bottom_osk_index) {
-            case BottomOSKIndex::LowerCase:
-                ui->button_ok->click();
-                break;
-            case BottomOSKIndex::UpperCase:
-                ui->button_ok_shift->click();
-                break;
-            case BottomOSKIndex::NumberPad:
-                ui->button_ok_num->click();
-                break;
-            default:
-                break;
-            }
-        });
-
-        ui->line_edit_osk->setPlaceholderText(
-            QString::fromStdU16String(initialize_parameters.guide_text));
-        ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text));
-        ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length);
-        ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position);
-
-        ui->label_characters->setText(QStringLiteral("%1/%2")
-                                          .arg(initialize_parameters.initial_text.size())
-                                          .arg(initialize_parameters.max_text_length));
-        break;
-    }
-    case SwkbdTextDrawType::Box:
-    default: {
-        ui->topOSK->setCurrentIndex(1);
-
-        if (is_inline) {
-            return;
-        }
-
-        connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] {
-            if (static_cast<u32>(ui->text_edit_osk->toPlainText().length()) >
-                initialize_parameters.max_text_length) {
-                auto text_cursor = ui->text_edit_osk->textCursor();
-                ui->text_edit_osk->setTextCursor(text_cursor);
-                text_cursor.deletePreviousChar();
-            }
-
-            const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText());
-
-            const auto text_length = static_cast<u32>(ui->text_edit_osk->toPlainText().length());
-
-            ui->label_characters_box->setText(QStringLiteral("%1/%2")
-                                                  .arg(text_length)
-                                                  .arg(initialize_parameters.max_text_length));
-
-            ui->button_ok->setEnabled(is_valid);
-            ui->button_ok_shift->setEnabled(is_valid);
-            ui->button_ok_num->setEnabled(is_valid);
-
-            ui->text_edit_osk->setFocus();
-        });
-
-        connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] {
-            const auto new_cursor_position = ui->text_edit_osk->textCursor().position();
-
-            ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
-                                             new_cursor_position > 0);
-            ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
-                                                   new_cursor_position > 0);
-            ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
-                                                 new_cursor_position > 0);
-
-            ui->text_edit_osk->setFocus();
-        });
-
-        ui->text_edit_osk->setPlaceholderText(
-            QString::fromStdU16String(initialize_parameters.guide_text));
-        ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text));
-        ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0
-                                          ? QTextCursor::Start
-                                          : QTextCursor::End);
-
-        ui->label_characters_box->setText(QStringLiteral("%1/%2")
-                                              .arg(initialize_parameters.initial_text.size())
-                                              .arg(initialize_parameters.max_text_length));
-        break;
-    }
-    }
-}
-
-void QtSoftwareKeyboardDialog::SetControllerImage() {
-    const auto controller_type = Settings::values.players.GetValue()[8].connected
-                                     ? Settings::values.players.GetValue()[8].controller_type
-                                     : Settings::values.players.GetValue()[0].controller_type;
-
-    const QString theme = [] {
-        if (QIcon::themeName().contains(QStringLiteral("dark")) ||
-            QIcon::themeName().contains(QStringLiteral("midnight"))) {
-            return QStringLiteral("_dark");
-        } else {
-            return QString{};
-        }
-    }();
-
-    switch (controller_type) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::GameCube:
-        ui->icon_controller->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
-        ui->icon_controller_shift->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
-        ui->icon_controller_num->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
-        break;
-    case Settings::ControllerType::DualJoyconDetached:
-        ui->icon_controller->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
-        ui->icon_controller_shift->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
-        ui->icon_controller_num->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
-        break;
-    case Settings::ControllerType::LeftJoycon:
-        ui->icon_controller->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
-                .arg(theme));
-        ui->icon_controller_shift->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
-                .arg(theme));
-        ui->icon_controller_num->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
-                .arg(theme));
-        break;
-    case Settings::ControllerType::RightJoycon:
-        ui->icon_controller->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
-                .arg(theme));
-        ui->icon_controller_shift->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
-                .arg(theme));
-        ui->icon_controller_num->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
-                .arg(theme));
-        break;
-    case Settings::ControllerType::Handheld:
-        ui->icon_controller->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
-        ui->icon_controller_shift->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
-        ui->icon_controller_num->setStyleSheet(
-            QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
-        break;
-    default:
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::DisableKeyboardButtons() {
-    switch (bottom_osk_index) {
-    case BottomOSKIndex::LowerCase:
-    case BottomOSKIndex::UpperCase:
-    default: {
-        for (const auto& keys : keyboard_buttons) {
-            for (const auto& rows : keys) {
-                for (auto* button : rows) {
-                    if (!button) {
-                        continue;
-                    }
-
-                    button->setEnabled(true);
-                }
-            }
-        }
-
-        const auto& key_disable_flags = initialize_parameters.key_disable_flags;
-
-        ui->button_space->setDisabled(key_disable_flags.space);
-        ui->button_space_shift->setDisabled(key_disable_flags.space);
-
-        ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username);
-
-        ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username);
-
-        ui->button_slash->setDisabled(key_disable_flags.slash);
-
-        ui->button_1->setDisabled(key_disable_flags.numbers);
-        ui->button_2->setDisabled(key_disable_flags.numbers);
-        ui->button_3->setDisabled(key_disable_flags.numbers);
-        ui->button_4->setDisabled(key_disable_flags.numbers);
-        ui->button_5->setDisabled(key_disable_flags.numbers);
-        ui->button_6->setDisabled(key_disable_flags.numbers);
-        ui->button_7->setDisabled(key_disable_flags.numbers);
-        ui->button_8->setDisabled(key_disable_flags.numbers);
-        ui->button_9->setDisabled(key_disable_flags.numbers);
-        ui->button_0->setDisabled(key_disable_flags.numbers);
-
-        ui->button_return->setEnabled(initialize_parameters.enable_return_button);
-        ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button);
-        break;
-    }
-    case BottomOSKIndex::NumberPad: {
-        for (const auto& rows : numberpad_buttons) {
-            for (auto* button : rows) {
-                if (!button) {
-                    continue;
-                }
-
-                button->setEnabled(true);
-            }
-        }
-        break;
-    }
-    }
-}
-
-void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() {
-    if (is_inline) {
-        ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length);
-        ui->button_ok_shift->setEnabled(current_text.size() >=
-                                        initialize_parameters.min_text_length);
-        ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length);
-
-        ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
-                                         cursor_position > 0);
-        ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
-                                               cursor_position > 0);
-        ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
-                                             cursor_position > 0);
-    } else {
-        const auto text_length = [this] {
-            if (ui->topOSK->currentIndex() == 1) {
-                return static_cast<u32>(ui->text_edit_osk->toPlainText().length());
-            } else {
-                return static_cast<u32>(ui->line_edit_osk->text().length());
-            }
-        }();
-
-        const auto normal_cursor_position = [this] {
-            if (ui->topOSK->currentIndex() == 1) {
-                return ui->text_edit_osk->textCursor().position();
-            } else {
-                return ui->line_edit_osk->cursorPosition();
-            }
-        }();
-
-        ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length);
-        ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length);
-        ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length);
-
-        ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
-                                         normal_cursor_position > 0);
-        ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
-                                               normal_cursor_position > 0);
-        ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
-                                             normal_cursor_position > 0);
-    }
-}
-
-bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) {
-    const auto& key_disable_flags = initialize_parameters.key_disable_flags;
-
-    const auto input_text_length = static_cast<u32>(input_text.length());
-
-    if (input_text_length < initialize_parameters.min_text_length ||
-        input_text_length > initialize_parameters.max_text_length) {
-        return false;
-    }
-
-    if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) {
-        return false;
-    }
-
-    if ((key_disable_flags.at || key_disable_flags.username) &&
-        input_text.contains(QLatin1Char{'@'})) {
-        return false;
-    }
-
-    if ((key_disable_flags.percent || key_disable_flags.username) &&
-        input_text.contains(QLatin1Char{'%'})) {
-        return false;
-    }
-
-    if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) {
-        return false;
-    }
-
-    if ((key_disable_flags.backslash || key_disable_flags.username) &&
-        input_text.contains(QLatin1Char('\\'))) {
-        return false;
-    }
-
-    if (key_disable_flags.numbers &&
-        std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) {
-        return false;
-    }
-
-    if (bottom_osk_index == BottomOSKIndex::NumberPad &&
-        std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) {
-        return false;
-    }
-
-    return true;
-}
-
-void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() {
-    switch (bottom_osk_index) {
-    case BottomOSKIndex::LowerCase:
-        bottom_osk_index = BottomOSKIndex::UpperCase;
-        ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
-
-        ui->button_shift_shift->setStyleSheet(
-            QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);"
-                           "\nbackground-position: left top;"
-                           "\nbackground-repeat: no-repeat;"
-                           "\nbackground-origin: content;"));
-
-        ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
-        ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
-        break;
-    case BottomOSKIndex::UpperCase:
-        if (caps_lock_enabled) {
-            caps_lock_enabled = false;
-
-            ui->button_shift_shift->setStyleSheet(
-                QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);"
-                               "\nbackground-position: left top;"
-                               "\nbackground-repeat: no-repeat;"
-                               "\nbackground-origin: content;"));
-
-            ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
-            ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
-
-            ui->label_shift_shift->setText(QStringLiteral("Caps Lock"));
-
-            bottom_osk_index = BottomOSKIndex::LowerCase;
-            ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
-        } else {
-            caps_lock_enabled = true;
-
-            ui->button_shift_shift->setStyleSheet(
-                QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_on.png);"
-                               "\nbackground-position: left top;"
-                               "\nbackground-repeat: no-repeat;"
-                               "\nbackground-origin: content;"));
-
-            ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
-            ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
-
-            ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off"));
-        }
-        break;
-    case BottomOSKIndex::NumberPad:
-    default:
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) {
-    if (button == ui->button_ampersand) {
-        if (ui->topOSK->currentIndex() == 1) {
-            ui->text_edit_osk->insertPlainText(QStringLiteral("&"));
-        } else {
-            ui->line_edit_osk->insert(QStringLiteral("&"));
-        }
-        return;
-    }
-
-    if (button == ui->button_return || button == ui->button_return_shift) {
-        if (ui->topOSK->currentIndex() == 1) {
-            ui->text_edit_osk->insertPlainText(QStringLiteral("\n"));
-        } else {
-            ui->line_edit_osk->insert(QStringLiteral("\n"));
-        }
-        return;
-    }
-
-    if (button == ui->button_space || button == ui->button_space_shift) {
-        if (ui->topOSK->currentIndex() == 1) {
-            ui->text_edit_osk->insertPlainText(QStringLiteral(" "));
-        } else {
-            ui->line_edit_osk->insert(QStringLiteral(" "));
-        }
-        return;
-    }
-
-    if (button == ui->button_shift || button == ui->button_shift_shift) {
-        ChangeBottomOSKIndex();
-        return;
-    }
-
-    if (button == ui->button_backspace || button == ui->button_backspace_shift ||
-        button == ui->button_backspace_num) {
-        if (ui->topOSK->currentIndex() == 1) {
-            auto text_cursor = ui->text_edit_osk->textCursor();
-            ui->text_edit_osk->setTextCursor(text_cursor);
-            text_cursor.deletePreviousChar();
-        } else {
-            ui->line_edit_osk->backspace();
-        }
-        return;
-    }
-
-    if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) {
-        if (ui->topOSK->currentIndex() == 1) {
-            emit SubmitNormalText(SwkbdResult::Ok,
-                                  ui->text_edit_osk->toPlainText().toStdU16String());
-        } else {
-            emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String());
-        }
-        return;
-    }
-
-    if (ui->topOSK->currentIndex() == 1) {
-        ui->text_edit_osk->insertPlainText(button->text());
-    } else {
-        ui->line_edit_osk->insert(button->text());
-    }
-
-    // Revert the keyboard to lowercase if the shift key is active.
-    if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) {
-        // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
-        // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
-        caps_lock_enabled = true;
-        ChangeBottomOSKIndex();
-    }
-}
-
-void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) {
-    if (!button->isEnabled()) {
-        return;
-    }
-
-    if (button == ui->button_ampersand) {
-        InlineTextInsertString(u"&");
-        return;
-    }
-
-    if (button == ui->button_return || button == ui->button_return_shift) {
-        InlineTextInsertString(u"\n");
-        return;
-    }
-
-    if (button == ui->button_space || button == ui->button_space_shift) {
-        InlineTextInsertString(u" ");
-        return;
-    }
-
-    if (button == ui->button_shift || button == ui->button_shift_shift) {
-        ChangeBottomOSKIndex();
-        return;
-    }
-
-    if (button == ui->button_backspace || button == ui->button_backspace_shift ||
-        button == ui->button_backspace_num) {
-        if (cursor_position <= 0 || current_text.empty()) {
-            cursor_position = 0;
-            return;
-        }
-
-        --cursor_position;
-
-        current_text.erase(cursor_position, 1);
-
-        SetBackspaceOkEnabled();
-
-        emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position);
-        return;
-    }
-
-    if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) {
-        emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position);
-        return;
-    }
-
-    InlineTextInsertString(button->text().toStdU16String());
-
-    // Revert the keyboard to lowercase if the shift key is active.
-    if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) {
-        // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
-        // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
-        caps_lock_enabled = true;
-        ChangeBottomOSKIndex();
-    }
-}
-
-void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) {
-    if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) {
-        return;
-    }
-
-    current_text.insert(cursor_position, string);
-
-    cursor_position += static_cast<s32>(string.size());
-
-    SetBackspaceOkEnabled();
-
-    emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position);
-}
-
-void QtSoftwareKeyboardDialog::SetupMouseHover() {
-    // setFocus() has a bug where continuously changing focus will cause the focus UI to
-    // mysteriously disappear. A workaround we have found is using the mouse to hover over
-    // the buttons to act in place of the button focus. As a result, we will have to set
-    // a blank cursor when hovering over all the buttons and set a no focus policy so the
-    // buttons do not stay in focus in addition to the mouse hover.
-    for (auto* button : all_buttons) {
-        button->setCursor(QCursor(Qt::BlankCursor));
-        button->setFocusPolicy(Qt::NoFocus);
-    }
-}
-
-template <HIDButton... T>
-void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() {
-    const auto f = [this](HIDButton button) {
-        if (input_interpreter->IsButtonPressedOnce(button)) {
-            TranslateButtonPress(button);
-        }
-    };
-
-    (f(T), ...);
-}
-
-template <HIDButton... T>
-void QtSoftwareKeyboardDialog::HandleButtonHold() {
-    const auto f = [this](HIDButton button) {
-        if (input_interpreter->IsButtonHeld(button)) {
-            TranslateButtonPress(button);
-        }
-    };
-
-    (f(T), ...);
-}
-
-void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
-    switch (button) {
-    case HIDButton::A:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-        case BottomOSKIndex::UpperCase:
-            keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-            numberpad_buttons[row][column]->click();
-            break;
-        default:
-            break;
-        }
-        break;
-    case HIDButton::B:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_backspace->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_backspace_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-            ui->button_backspace_num->click();
-            break;
-        default:
-            break;
-        }
-        break;
-    case HIDButton::X:
-        if (is_inline) {
-            emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
-        } else {
-            if (ui->topOSK->currentIndex() == 1) {
-                emit SubmitNormalText(SwkbdResult::Cancel,
-                                      ui->text_edit_osk->toPlainText().toStdU16String());
-            } else {
-                emit SubmitNormalText(SwkbdResult::Cancel,
-                                      ui->line_edit_osk->text().toStdU16String());
-            }
-        }
-        break;
-    case HIDButton::Y:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_space->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_space_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-        default:
-            break;
-        }
-        break;
-    case HIDButton::LStick:
-    case HIDButton::RStick:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_shift->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_shift_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-        default:
-            break;
-        }
-        break;
-    case HIDButton::L:
-        MoveTextCursorDirection(Direction::Left);
-        break;
-    case HIDButton::R:
-        MoveTextCursorDirection(Direction::Right);
-        break;
-    case HIDButton::Plus:
-        switch (bottom_osk_index) {
-        case BottomOSKIndex::LowerCase:
-            ui->button_ok->click();
-            break;
-        case BottomOSKIndex::UpperCase:
-            ui->button_ok_shift->click();
-            break;
-        case BottomOSKIndex::NumberPad:
-            ui->button_ok_num->click();
-            break;
-        default:
-            break;
-        }
-        break;
-    case HIDButton::DLeft:
-    case HIDButton::LStickLeft:
-    case HIDButton::RStickLeft:
-        MoveButtonDirection(Direction::Left);
-        break;
-    case HIDButton::DUp:
-    case HIDButton::LStickUp:
-    case HIDButton::RStickUp:
-        MoveButtonDirection(Direction::Up);
-        break;
-    case HIDButton::DRight:
-    case HIDButton::LStickRight:
-    case HIDButton::RStickRight:
-        MoveButtonDirection(Direction::Right);
-        break;
-    case HIDButton::DDown:
-    case HIDButton::LStickDown:
-    case HIDButton::RStickDown:
-        MoveButtonDirection(Direction::Down);
-        break;
-    default:
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) {
-    // Changes the row or column index depending on the direction.
-    auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) {
-        switch (direction) {
-        case Direction::Left:
-            column = (column + max_columns - 1) % max_columns;
-            break;
-        case Direction::Up:
-            row = (row + max_rows - 1) % max_rows;
-            break;
-        case Direction::Right:
-            column = (column + 1) % max_columns;
-            break;
-        case Direction::Down:
-            row = (row + 1) % max_rows;
-            break;
-        default:
-            break;
-        }
-    };
-
-    switch (bottom_osk_index) {
-    case BottomOSKIndex::LowerCase:
-    case BottomOSKIndex::UpperCase: {
-        const auto index = static_cast<std::size_t>(bottom_osk_index);
-
-        const auto* const prev_button = keyboard_buttons[index][row][column];
-        move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL);
-        auto* curr_button = keyboard_buttons[index][row][column];
-
-        while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) {
-            move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL);
-            curr_button = keyboard_buttons[index][row][column];
-        }
-
-        // This is a workaround for setFocus() randomly not showing focus in the UI
-        QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
-        break;
-    }
-    case BottomOSKIndex::NumberPad: {
-        const auto* const prev_button = numberpad_buttons[row][column];
-        move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD);
-        auto* curr_button = numberpad_buttons[row][column];
-
-        while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) {
-            move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD);
-            curr_button = numberpad_buttons[row][column];
-        }
-
-        // This is a workaround for setFocus() randomly not showing focus in the UI
-        QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
-        break;
-    }
-    default:
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) {
-    switch (direction) {
-    case Direction::Left:
-        if (is_inline) {
-            if (cursor_position <= 0) {
-                cursor_position = 0;
-            } else {
-                --cursor_position;
-                emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position);
-            }
-        } else {
-            if (ui->topOSK->currentIndex() == 1) {
-                ui->text_edit_osk->moveCursor(QTextCursor::Left);
-            } else {
-                ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1);
-            }
-        }
-        break;
-    case Direction::Right:
-        if (is_inline) {
-            if (cursor_position >= static_cast<s32>(current_text.size())) {
-                cursor_position = static_cast<s32>(current_text.size());
-            } else {
-                ++cursor_position;
-                emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position);
-            }
-        } else {
-            if (ui->topOSK->currentIndex() == 1) {
-                ui->text_edit_osk->moveCursor(QTextCursor::Right);
-            } else {
-                ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1);
-            }
-        }
-        break;
-    default:
-        break;
-    }
-}
-
-void QtSoftwareKeyboardDialog::StartInputThread() {
-    if (input_thread_running) {
-        return;
-    }
-
-    input_thread_running = true;
-
-    input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this);
-}
-
-void QtSoftwareKeyboardDialog::StopInputThread() {
-    input_thread_running = false;
-
-    if (input_thread.joinable()) {
-        input_thread.join();
-    }
-
-    if (input_interpreter) {
-        input_interpreter->ResetButtonStates();
-    }
-}
-
-void QtSoftwareKeyboardDialog::InputThread() {
-    while (input_thread_running) {
-        input_interpreter->PollInput();
-
-        HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y,
-                                HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R,
-                                HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp,
-                                HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
-                                HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
-                                HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
-                                HIDButton::RStickDown>();
-
-        HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp,
-                         HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
-                         HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
-                         HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
-                         HIDButton::RStickDown>();
-
-        std::this_thread::sleep_for(std::chrono::milliseconds(50));
-    }
+std::u16string QtSoftwareKeyboardDialog::GetText() const {
+    return text;
 }
 
 QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {
-    connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window,
-            &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window,
-            &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window,
-            &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window,
-            &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window,
-            &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window,
-            &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection);
-    connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window,
-            &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection);
-    connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this,
-            &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection);
-    connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this,
-            &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection);
+    connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window,
+            &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection);
+    connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window,
+            &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection);
+    connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this,
+            &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection);
 }
 
 QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
 
-void QtSoftwareKeyboard::InitializeKeyboard(
-    bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
-    std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
-    std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-        submit_inline_callback_) {
-    if (is_inline) {
-        submit_inline_callback = std::move(submit_inline_callback_);
-    } else {
-        submit_normal_callback = std::move(submit_normal_callback_);
-    }
-
-    LOG_INFO(Service_AM,
-             "\nKeyboardInitializeParameters:"
-             "\nok_text={}"
-             "\nheader_text={}"
-             "\nsub_text={}"
-             "\nguide_text={}"
-             "\ninitial_text={}"
-             "\nmax_text_length={}"
-             "\nmin_text_length={}"
-             "\ninitial_cursor_position={}"
-             "\ntype={}"
-             "\npassword_mode={}"
-             "\ntext_draw_type={}"
-             "\nkey_disable_flags={}"
-             "\nuse_blur_background={}"
-             "\nenable_backspace_button={}"
-             "\nenable_return_button={}"
-             "\ndisable_cancel_button={}",
-             Common::UTF16ToUTF8(initialize_parameters.ok_text),
-             Common::UTF16ToUTF8(initialize_parameters.header_text),
-             Common::UTF16ToUTF8(initialize_parameters.sub_text),
-             Common::UTF16ToUTF8(initialize_parameters.guide_text),
-             Common::UTF16ToUTF8(initialize_parameters.initial_text),
-             initialize_parameters.max_text_length, initialize_parameters.min_text_length,
-             initialize_parameters.initial_cursor_position, initialize_parameters.type,
-             initialize_parameters.password_mode, initialize_parameters.text_draw_type,
-             initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background,
-             initialize_parameters.enable_backspace_button,
-             initialize_parameters.enable_return_button,
-             initialize_parameters.disable_cancel_button);
-
-    emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters));
+void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out,
+                                     Core::Frontend::SoftwareKeyboardParameters parameters) const {
+    text_output = std::move(out);
+    emit MainWindowGetText(parameters);
 }
 
-void QtSoftwareKeyboard::ShowNormalKeyboard() const {
-    emit MainWindowShowNormalKeyboard();
+void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message,
+                                             std::function<void()> finished_check_) const {
+    finished_check = std::move(finished_check_);
+    emit MainWindowTextCheckDialog(error_message);
 }
 
-void QtSoftwareKeyboard::ShowTextCheckDialog(
-    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-    std::u16string text_check_message) const {
-    emit MainWindowShowTextCheckDialog(text_check_result, text_check_message);
+void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
+    // Acquire the HLE mutex
+    std::lock_guard lock{HLE::g_hle_lock};
+    text_output(std::move(text));
 }
 
-void QtSoftwareKeyboard::ShowInlineKeyboard(
-    Core::Frontend::InlineAppearParameters appear_parameters) const {
-    LOG_INFO(Service_AM,
-             "\nInlineAppearParameters:"
-             "\nmax_text_length={}"
-             "\nmin_text_length={}"
-             "\nkey_top_scale_x={}"
-             "\nkey_top_scale_y={}"
-             "\nkey_top_translate_x={}"
-             "\nkey_top_translate_y={}"
-             "\ntype={}"
-             "\nkey_disable_flags={}"
-             "\nkey_top_as_floating={}"
-             "\nenable_backspace_button={}"
-             "\nenable_return_button={}"
-             "\ndisable_cancel_button={}",
-             appear_parameters.max_text_length, appear_parameters.min_text_length,
-             appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
-             appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
-             appear_parameters.type, appear_parameters.key_disable_flags.raw,
-             appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
-             appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
-
-    emit MainWindowShowInlineKeyboard(std::move(appear_parameters));
-}
-
-void QtSoftwareKeyboard::HideInlineKeyboard() const {
-    emit MainWindowHideInlineKeyboard();
-}
-
-void QtSoftwareKeyboard::InlineTextChanged(
-    Core::Frontend::InlineTextParameters text_parameters) const {
-    LOG_INFO(Service_AM,
-             "\nInlineTextParameters:"
-             "\ninput_text={}"
-             "\ncursor_position={}",
-             Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
-
-    emit MainWindowInlineTextChanged(std::move(text_parameters));
-}
-
-void QtSoftwareKeyboard::ExitKeyboard() const {
-    emit MainWindowExitKeyboard();
-}
-
-void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result,
-                                          std::u16string submitted_text) const {
-    submit_normal_callback(result, submitted_text);
-}
-
-void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
-                                          std::u16string submitted_text,
-                                          s32 cursor_position) const {
-    submit_inline_callback(reply_type, submitted_text, cursor_position);
+void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
+    // Acquire the HLE mutex
+    std::lock_guard lock{HLE::g_hle_lock};
+    finished_check();
 }
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h
index 1a03c098c..9e1094cce 100755
--- a/src/yuzu/applets/software_keyboard.h
+++ b/src/yuzu/applets/software_keyboard.h
@@ -1,228 +1,54 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 yuzu Emulator Project
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
 #pragma once
 
-#include <array>
-#include <atomic>
-#include <memory>
-#include <thread>
-
 #include <QDialog>
 #include <QValidator>
-
 #include "core/frontend/applets/software_keyboard.h"
 
-enum class HIDButton : u8;
-
-class InputInterpreter;
-
-namespace Core {
-class System;
-}
-
-namespace Ui {
-class QtSoftwareKeyboardDialog;
-}
-
 class GMainWindow;
+class QDialogButtonBox;
+class QLabel;
+class QLineEdit;
+class QVBoxLayout;
+class QtSoftwareKeyboard;
+
+class QtSoftwareKeyboardValidator final : public QValidator {
+public:
+    explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters);
+    State validate(QString& input, int& pos) const override;
+
+private:
+    Core::Frontend::SoftwareKeyboardParameters parameters;
+};
 
 class QtSoftwareKeyboardDialog final : public QDialog {
     Q_OBJECT
 
 public:
-    QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_,
-                             Core::Frontend::KeyboardInitializeParameters initialize_parameters_);
+    QtSoftwareKeyboardDialog(QWidget* parent,
+                             Core::Frontend::SoftwareKeyboardParameters parameters);
     ~QtSoftwareKeyboardDialog() override;
 
-    void ShowNormalKeyboard(QPoint pos, QSize size);
-
-    void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                             std::u16string text_check_message);
-
-    void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos,
-                            QSize size);
-
-    void HideInlineKeyboard();
-
-    void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
-
-    void ExitKeyboard();
-
-signals:
-    void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
-                          std::u16string submitted_text) const;
-
-    void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
-                          std::u16string submitted_text, s32 cursor_position) const;
-
-public slots:
-    void open() override;
+    void accept() override;
     void reject() override;
 
-protected:
-    /// We override the keyPressEvent for inputting text into the inline software keyboard.
-    void keyPressEvent(QKeyEvent* event) override;
+    std::u16string GetText() const;
 
 private:
-    enum class Direction {
-        Left,
-        Up,
-        Right,
-        Down,
-    };
+    std::u16string text;
 
-    enum class BottomOSKIndex {
-        LowerCase,
-        UpperCase,
-        NumberPad,
-    };
+    QDialogButtonBox* buttons;
+    QLabel* header_label;
+    QLabel* sub_label;
+    QLabel* guide_label;
+    QLabel* length_label;
+    QLineEdit* line_edit;
+    QVBoxLayout* layout;
 
-    /**
-     * Moves and resizes the window to a specified position and size.
-     *
-     * @param pos Top-left window position
-     * @param size Window size
-     */
-    void MoveAndResizeWindow(QPoint pos, QSize size);
-
-    /**
-     * Rescales all keyboard elements to account for High DPI displays.
-     *
-     * @param width Window width
-     * @param height Window height
-     * @param dpi_scale Display scaling factor
-     */
-    void RescaleKeyboardElements(float width, float height, float dpi_scale);
-
-    /// Sets the keyboard type based on initialize_parameters.
-    void SetKeyboardType();
-
-    /// Sets the password mode based on initialize_parameters.
-    void SetPasswordMode();
-
-    /// Sets the text draw type based on initialize_parameters.
-    void SetTextDrawType();
-
-    /// Sets the controller image at the bottom left of the software keyboard.
-    void SetControllerImage();
-
-    /// Disables buttons based on initialize_parameters.
-    void DisableKeyboardButtons();
-
-    /// Changes whether the backspace or/and ok buttons should be enabled or disabled.
-    void SetBackspaceOkEnabled();
-
-    /**
-     * Validates the input text sent in based on the parameters in initialize_parameters.
-     *
-     * @param input_text Input text
-     *
-     * @returns True if the input text is valid, false otherwise.
-     */
-    bool ValidateInputText(const QString& input_text);
-
-    /// Switches between LowerCase and UpperCase (Shift and Caps Lock)
-    void ChangeBottomOSKIndex();
-
-    /// Processes a keyboard button click from the UI as normal keyboard input.
-    void NormalKeyboardButtonClicked(QPushButton* button);
-
-    /// Processes a keyboard button click from the UI as inline keyboard input.
-    void InlineKeyboardButtonClicked(QPushButton* button);
-
-    /**
-     * Inserts a string of arbitrary length into the current_text at the current cursor position.
-     * This is only used for the inline software keyboard.
-     */
-    void InlineTextInsertString(std::u16string_view string);
-
-    /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once.
-    void SetupMouseHover();
-
-    /**
-     * Handles button presses and converts them into keyboard input.
-     *
-     * @tparam HIDButton The list of buttons that can be converted into keyboard input.
-     */
-    template <HIDButton... T>
-    void HandleButtonPressedOnce();
-
-    /**
-     * Handles button holds and converts them into keyboard input.
-     *
-     * @tparam HIDButton The list of buttons that can be converted into keyboard input.
-     */
-    template <HIDButton... T>
-    void HandleButtonHold();
-
-    /**
-     * Translates a button press to focus or click a keyboard button.
-     *
-     * @param button The button press to process.
-     */
-    void TranslateButtonPress(HIDButton button);
-
-    /**
-     * Moves the focus of a button in a certain direction.
-     *
-     * @param direction The direction to move.
-     */
-    void MoveButtonDirection(Direction direction);
-
-    /**
-     * Moves the text cursor in a certain direction.
-     *
-     * @param direction The direction to move.
-     */
-    void MoveTextCursorDirection(Direction direction);
-
-    void StartInputThread();
-    void StopInputThread();
-
-    /// The thread where input is being polled and processed.
-    void InputThread();
-
-    std::unique_ptr<Ui::QtSoftwareKeyboardDialog> ui;
-
-    Core::System& system;
-
-    // True if it is the inline software keyboard.
-    bool is_inline;
-
-    // Common software keyboard initialize parameters.
-    Core::Frontend::KeyboardInitializeParameters initialize_parameters;
-
-    // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden.
-    std::u16string current_text;
-    s32 cursor_position{0};
-
-    static constexpr std::size_t NUM_ROWS_NORMAL = 5;
-    static constexpr std::size_t NUM_COLUMNS_NORMAL = 12;
-    static constexpr std::size_t NUM_ROWS_NUMPAD = 4;
-    static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4;
-
-    // Stores the normal keyboard layout.
-    std::array<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2>
-        keyboard_buttons;
-    // Stores the numberpad keyboard layout.
-    std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons;
-
-    // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons.
-    std::array<QPushButton*, 110> all_buttons;
-
-    std::size_t row{0};
-    std::size_t column{0};
-
-    BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase};
-    std::atomic<bool> caps_lock_enabled{false};
-
-    std::unique_ptr<InputInterpreter> input_interpreter;
-
-    std::thread input_thread;
-
-    std::atomic<bool> input_thread_running{};
+    Core::Frontend::SoftwareKeyboardParameters parameters;
 };
 
 class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
@@ -232,54 +58,19 @@ public:
     explicit QtSoftwareKeyboard(GMainWindow& parent);
     ~QtSoftwareKeyboard() override;
 
-    void InitializeKeyboard(
-        bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
-        std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
-            submit_normal_callback_,
-        std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-            submit_inline_callback_) override;
-
-    void ShowNormalKeyboard() const override;
-
-    void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                             std::u16string text_check_message) const override;
-
-    void ShowInlineKeyboard(
-        Core::Frontend::InlineAppearParameters appear_parameters) const override;
-
-    void HideInlineKeyboard() const override;
-
-    void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override;
-
-    void ExitKeyboard() const override;
+    void RequestText(std::function<void(std::optional<std::u16string>)> out,
+                     Core::Frontend::SoftwareKeyboardParameters parameters) const override;
+    void SendTextCheckDialog(std::u16string error_message,
+                             std::function<void()> finished_check_) const override;
 
 signals:
-    void MainWindowInitializeKeyboard(
-        bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const;
-
-    void MainWindowShowNormalKeyboard() const;
-
-    void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                                       std::u16string text_check_message) const;
-
-    void MainWindowShowInlineKeyboard(
-        Core::Frontend::InlineAppearParameters appear_parameters) const;
-
-    void MainWindowHideInlineKeyboard() const;
-
-    void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const;
-
-    void MainWindowExitKeyboard() const;
+    void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const;
+    void MainWindowTextCheckDialog(std::u16string error_message) const;
 
 private:
-    void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
-                          std::u16string submitted_text) const;
+    void MainWindowFinishedText(std::optional<std::u16string> text);
+    void MainWindowFinishedCheckDialog();
 
-    void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
-                          std::u16string submitted_text, s32 cursor_position) const;
-
-    mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
-        submit_normal_callback;
-    mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
-        submit_inline_callback;
+    mutable std::function<void(std::optional<std::u16string>)> text_output;
+    mutable std::function<void()> finished_check;
 };
diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp
index aad06ac2a..a93733b26 100755
--- a/src/yuzu/discord_impl.cpp
+++ b/src/yuzu/discord_impl.cpp
@@ -38,7 +38,7 @@ void DiscordImpl::Update() {
     if (Core::System::GetInstance().IsPoweredOn())
         Core::System::GetInstance().GetAppLoader().ReadTitle(title);
     DiscordRichPresence presence{};
-    presence.largeImageKey = "yuzu_logo_ea";
+    presence.largeImageKey = "yuzu_logo";
     presence.largeImageText = "yuzu is an emulator for the Nintendo Switch";
     if (Core::System::GetInstance().IsPoweredOn()) {
         presence.state = title.c_str();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f66b6c476..23ea4983d 100755
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -101,7 +101,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 #include "core/settings.h"
 #include "core/telemetry_session.h"
 #include "input_common/main.h"
-#include "util/overlay_dialog.h"
 #include "video_core/gpu.h"
 #include "video_core/shader_notify.h"
 #include "yuzu/about_dialog.h"
@@ -226,8 +225,6 @@ GMainWindow::GMainWindow()
     SetDiscordEnabled(UISettings::values.enable_discord_presence);
     discord_rpc->Update();
 
-    RegisterMetaTypes();
-
     InitializeWidgets();
     InitializeDebugWidgets();
     InitializeRecentFileMenuActions();
@@ -376,55 +373,6 @@ GMainWindow::~GMainWindow() {
         delete render_window;
 }
 
-void GMainWindow::RegisterMetaTypes() {
-    // Register integral and floating point types
-    qRegisterMetaType<u8>("u8");
-    qRegisterMetaType<u16>("u16");
-    qRegisterMetaType<u32>("u32");
-    qRegisterMetaType<u64>("u64");
-    qRegisterMetaType<u128>("u128");
-    qRegisterMetaType<s8>("s8");
-    qRegisterMetaType<s16>("s16");
-    qRegisterMetaType<s32>("s32");
-    qRegisterMetaType<s64>("s64");
-    qRegisterMetaType<f32>("f32");
-    qRegisterMetaType<f64>("f64");
-
-    // Register string types
-    qRegisterMetaType<std::string>("std::string");
-    qRegisterMetaType<std::wstring>("std::wstring");
-    qRegisterMetaType<std::u8string>("std::u8string");
-    qRegisterMetaType<std::u16string>("std::u16string");
-    qRegisterMetaType<std::u32string>("std::u32string");
-    qRegisterMetaType<std::string_view>("std::string_view");
-    qRegisterMetaType<std::wstring_view>("std::wstring_view");
-    qRegisterMetaType<std::u8string_view>("std::u8string_view");
-    qRegisterMetaType<std::u16string_view>("std::u16string_view");
-    qRegisterMetaType<std::u32string_view>("std::u32string_view");
-
-    // Register applet types
-
-    // Controller Applet
-    qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
-
-    // Software Keyboard Applet
-    qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
-        "Core::Frontend::KeyboardInitializeParameters");
-    qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
-        "Core::Frontend::InlineAppearParameters");
-    qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
-    qRegisterMetaType<Service::AM::Applets::SwkbdResult>("Service::AM::Applets::SwkbdResult");
-    qRegisterMetaType<Service::AM::Applets::SwkbdTextCheckResult>(
-        "Service::AM::Applets::SwkbdTextCheckResult");
-    qRegisterMetaType<Service::AM::Applets::SwkbdReplyType>("Service::AM::Applets::SwkbdReplyType");
-
-    // Web Browser Applet
-    qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
-
-    // Register loader types
-    qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
-}
-
 void GMainWindow::ControllerSelectorReconfigureControllers(
     const Core::Frontend::ControllerParameters& parameters) {
     QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
@@ -464,112 +412,25 @@ void GMainWindow::ProfileSelectorSelectProfile() {
     emit ProfileSelectorFinishedSelection(uuid);
 }
 
-void GMainWindow::SoftwareKeyboardInitialize(
-    bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
-    if (software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is already initialized!");
+void GMainWindow::SoftwareKeyboardGetText(
+    const Core::Frontend::SoftwareKeyboardParameters& parameters) {
+    QtSoftwareKeyboardDialog dialog(this, parameters);
+    dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
+                          Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
+                          Qt::WindowCloseButtonHint);
+    dialog.setWindowModality(Qt::WindowModal);
+
+    if (dialog.exec() == QDialog::Rejected) {
+        emit SoftwareKeyboardFinishedText(std::nullopt);
         return;
     }
 
-    software_keyboard = new QtSoftwareKeyboardDialog(render_window, Core::System::GetInstance(),
-                                                     is_inline, std::move(initialize_parameters));
-
-    if (is_inline) {
-        connect(
-            software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this,
-            [this](Service::AM::Applets::SwkbdReplyType reply_type, std::u16string submitted_text,
-                   s32 cursor_position) {
-                emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position);
-            },
-            Qt::QueuedConnection);
-    } else {
-        connect(
-            software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this,
-            [this](Service::AM::Applets::SwkbdResult result, std::u16string submitted_text) {
-                emit SoftwareKeyboardSubmitNormalText(result, submitted_text);
-            },
-            Qt::QueuedConnection);
-    }
+    emit SoftwareKeyboardFinishedText(dialog.GetText());
 }
 
-void GMainWindow::SoftwareKeyboardShowNormal() {
-    if (!software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
-        return;
-    }
-
-    const auto& layout = render_window->GetFramebufferLayout();
-
-    const auto x = layout.screen.left;
-    const auto y = layout.screen.top;
-    const auto w = layout.screen.GetWidth();
-    const auto h = layout.screen.GetHeight();
-
-    software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h));
-}
-
-void GMainWindow::SoftwareKeyboardShowTextCheck(
-    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-    std::u16string text_check_message) {
-    if (!software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
-        return;
-    }
-
-    software_keyboard->ShowTextCheckDialog(text_check_result, text_check_message);
-}
-
-void GMainWindow::SoftwareKeyboardShowInline(
-    Core::Frontend::InlineAppearParameters appear_parameters) {
-    if (!software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
-        return;
-    }
-
-    const auto& layout = render_window->GetFramebufferLayout();
-
-    const auto x =
-        static_cast<int>(layout.screen.left + (0.5f * layout.screen.GetWidth() *
-                                               ((2.0f * appear_parameters.key_top_translate_x) +
-                                                (1.0f - appear_parameters.key_top_scale_x))));
-    const auto y =
-        static_cast<int>(layout.screen.top + (layout.screen.GetHeight() *
-                                              ((2.0f * appear_parameters.key_top_translate_y) +
-                                               (1.0f - appear_parameters.key_top_scale_y))));
-    const auto w = static_cast<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x);
-    const auto h = static_cast<int>(layout.screen.GetHeight() * appear_parameters.key_top_scale_y);
-
-    software_keyboard->ShowInlineKeyboard(std::move(appear_parameters),
-                                          render_window->mapToGlobal(QPoint(x, y)), QSize(w, h));
-}
-
-void GMainWindow::SoftwareKeyboardHideInline() {
-    if (!software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
-        return;
-    }
-
-    software_keyboard->HideInlineKeyboard();
-}
-
-void GMainWindow::SoftwareKeyboardInlineTextChanged(
-    Core::Frontend::InlineTextParameters text_parameters) {
-    if (!software_keyboard) {
-        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
-        return;
-    }
-
-    software_keyboard->InlineTextChanged(std::move(text_parameters));
-}
-
-void GMainWindow::SoftwareKeyboardExit() {
-    if (!software_keyboard) {
-        return;
-    }
-
-    software_keyboard->ExitKeyboard();
-
-    software_keyboard = nullptr;
+void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) {
+    QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message));
+    emit SoftwareKeyboardFinishedCheckDialog();
 }
 
 void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
@@ -1115,10 +976,6 @@ void GMainWindow::ConnectWidgetEvents() {
     connect(this, &GMainWindow::EmulationStopping, render_window,
             &GRenderWindow::OnEmulationStopping);
 
-    // Software Keyboard Applet
-    connect(this, &GMainWindow::EmulationStarting, this, &GMainWindow::SoftwareKeyboardExit);
-    connect(this, &GMainWindow::EmulationStopping, this, &GMainWindow::SoftwareKeyboardExit);
-
     connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
 }
 
@@ -2328,6 +2185,15 @@ void GMainWindow::OnStartGame() {
 
     emu_thread->SetRunning(true);
 
+    qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
+    qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>(
+        "Core::Frontend::SoftwareKeyboardParameters");
+    qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
+    qRegisterMetaType<std::string>("std::string");
+    qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>");
+    qRegisterMetaType<std::string_view>("std::string_view");
+    qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
+
     connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
 
     ui.action_Start->setEnabled(false);
@@ -2376,11 +2242,8 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
     BootGame(last_filename_booted, program_index);
 }
 
-void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
-    OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
-                         QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
-    dialog.exec();
-
+void GMainWindow::ErrorDisplayDisplayError(QString body) {
+    QMessageBox::critical(this, tr("Error Display"), body);
     emit ErrorDisplayFinished();
 }
 
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7f1e50a5b..04d37d4ae 100755
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -37,13 +37,9 @@ enum class GameListRemoveTarget;
 enum class InstalledEntryType;
 class GameListPlaceholder;
 
-class QtSoftwareKeyboardDialog;
-
 namespace Core::Frontend {
 struct ControllerParameters;
-struct InlineAppearParameters;
-struct InlineTextParameters;
-struct KeyboardInitializeParameters;
+struct SoftwareKeyboardParameters;
 } // namespace Core::Frontend
 
 namespace DiscordRPC {
@@ -61,11 +57,8 @@ class InputSubsystem;
 }
 
 namespace Service::AM::Applets {
-enum class SwkbdResult : u32;
-enum class SwkbdTextCheckResult : u32;
-enum class SwkbdReplyType : u32;
 enum class WebExitReason : u32;
-} // namespace Service::AM::Applets
+}
 
 enum class EmulatedDirectoryTarget {
     NAND,
@@ -135,10 +128,8 @@ signals:
 
     void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
 
-    void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result,
-                                          std::u16string submitted_text);
-    void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
-                                          std::u16string submitted_text, s32 cursor_position);
+    void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
+    void SoftwareKeyboardFinishedCheckDialog();
 
     void WebBrowserExtractOfflineRomFS();
     void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
@@ -148,24 +139,15 @@ public slots:
     void OnExecuteProgram(std::size_t program_index);
     void ControllerSelectorReconfigureControllers(
         const Core::Frontend::ControllerParameters& parameters);
-    void SoftwareKeyboardInitialize(
-        bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters);
-    void SoftwareKeyboardShowNormal();
-    void SoftwareKeyboardShowTextCheck(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
-                                       std::u16string text_check_message);
-    void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters);
-    void SoftwareKeyboardHideInline();
-    void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
-    void SoftwareKeyboardExit();
-    void ErrorDisplayDisplayError(QString error_code, QString error_text);
+    void ErrorDisplayDisplayError(QString body);
     void ProfileSelectorSelectProfile();
+    void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
+    void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
     void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
                                bool is_local);
     void OnAppFocusStateChanged(Qt::ApplicationState state);
 
 private:
-    void RegisterMetaTypes();
-
     void InitializeWidgets();
     void InitializeDebugWidgets();
     void InitializeRecentFileMenuActions();
@@ -352,9 +334,6 @@ private:
     // Disables the web applet for the rest of the emulated session
     bool disable_web_applet{};
 
-    // Applets
-    QtSoftwareKeyboardDialog* software_keyboard = nullptr;
-
 protected:
     void dropEvent(QDropEvent* event) override;
     void dragEnterEvent(QDragEnterEvent* event) override;