From f903d3161dd0e25f656c54fe23a9cdfa6d5c2575 Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Sat, 9 Feb 2019 15:01:58 +0100
Subject: [PATCH 1/5] ptm: move ptm_shared_extdata_id to header

---
 src/core/hle/service/ptm/ptm.cpp | 3 ---
 src/core/hle/service/ptm/ptm.h   | 3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 9ba14d407..f86ce78dc 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -23,9 +23,6 @@ namespace Service::PTM {
 /// Values for the default gamecoin.dat file
 static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29};
 
-/// Id of the SharedExtData archive used by the PTM process
-static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
-
 void Module::Interface::GetAdapterState(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp(ctx, 0x5, 0, 0);
 
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index e56a66972..ee29eb2e8 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -15,6 +15,9 @@ class System;
 
 namespace Service::PTM {
 
+/// Id of the SharedExtData archive used by the PTM process
+static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
+
 /// Charge levels used by PTM functions
 enum class ChargeLevels : u32 {
     CriticalBattery = 1,

From 041638ea4d6eb5f7ad5f60394e2b59a73b3336d0 Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Sat, 9 Feb 2019 17:00:57 +0100
Subject: [PATCH 2/5] applets: implement HLE mii selector applet

---
 src/citra_qt/CMakeLists.txt                   |   2 +
 src/citra_qt/applets/mii_selector.cpp         | 125 ++++++++++++++++++
 src/citra_qt/applets/mii_selector.h           |  48 +++++++
 src/citra_qt/main.cpp                         |   2 +
 src/core/CMakeLists.txt                       |   2 +
 src/core/core.cpp                             |   4 +
 src/core/core.h                               |   8 ++
 src/core/frontend/applets/default_applets.cpp |   2 +
 src/core/frontend/applets/mii_selector.cpp    |  27 ++++
 src/core/frontend/applets/mii_selector.h      |  56 ++++++++
 src/core/hle/applets/mii_selector.cpp         |  67 +++++++---
 src/core/hle/applets/mii_selector.h           |  25 +++-
 12 files changed, 350 insertions(+), 18 deletions(-)
 create mode 100644 src/citra_qt/applets/mii_selector.cpp
 create mode 100644 src/citra_qt/applets/mii_selector.h
 create mode 100644 src/core/frontend/applets/mii_selector.cpp
 create mode 100644 src/core/frontend/applets/mii_selector.h

diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 0cc4d1c68..5d1664a31 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -10,6 +10,8 @@ add_executable(citra-qt
     Info.plist
     aboutdialog.cpp
     aboutdialog.h
+    applets/mii_selector.cpp
+    applets/mii_selector.h
     applets/swkbd.cpp
     applets/swkbd.h
     bootmanager.cpp
diff --git a/src/citra_qt/applets/mii_selector.cpp b/src/citra_qt/applets/mii_selector.cpp
new file mode 100644
index 000000000..3b905eb33
--- /dev/null
+++ b/src/citra_qt/applets/mii_selector.cpp
@@ -0,0 +1,125 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <QMessageBox>
+#include <QString>
+#include <QVBoxLayout>
+#include "citra_qt/applets/mii_selector.h"
+#include "common/file_util.h"
+#include "core/file_sys/archive_extsavedata.h"
+#include "core/file_sys/file_backend.h"
+#include "core/hle/applets/buttons.h"
+#include "core/hle/service/ptm/ptm.h"
+
+QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_selector_)
+    : QDialog(parent), mii_selector(mii_selector_) {
+    Frontend::MiiSelectorConfig config = mii_selector->config;
+    layout = new QVBoxLayout;
+    combobox = new QComboBox;
+    buttons = new QDialogButtonBox;
+    // Initialize buttons
+    buttons->addButton(tr(AppletButton::Ok), QDialogButtonBox::ButtonRole::AcceptRole);
+    if (config.enable_cancel_button) {
+        buttons->addButton(tr(AppletButton::Cancel), QDialogButtonBox::ButtonRole::RejectRole);
+    }
+
+    setWindowTitle(config.title.empty() ? tr("Mii Selector")
+                                        : QString::fromStdU16String(config.title));
+
+    std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)};
+    FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
+
+    auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id);
+    if (!archive_result.Succeeded()) {
+        ShowNoMiis();
+        return;
+    }
+
+    auto archive = std::move(archive_result).Unwrap();
+
+    FileSys::Path file_path = "/CFL_DB.dat";
+    FileSys::Mode mode{};
+    mode.read_flag.Assign(1);
+
+    auto file_result = archive->OpenFile(file_path, mode);
+    if (!file_result.Succeeded()) {
+        ShowNoMiis();
+        return;
+    }
+
+    auto file = std::move(file_result).Unwrap();
+
+    u32 saved_miis_offset = 0x8;
+    // The Mii Maker has a 100 Mii limit on the 3ds
+    for (int i = 0; i < 100; ++i) {
+        HLE::Applets::MiiData mii;
+        std::array<u8, sizeof(mii)> mii_raw;
+        file->Read(saved_miis_offset, sizeof(mii), mii_raw.data());
+        std::memcpy(&mii, mii_raw.data(), sizeof(mii));
+        if (mii.mii_id != 0) {
+            std::u16string name(sizeof(mii.mii_name), '\0');
+            std::memcpy(&name[0], mii.mii_name.data(), sizeof(mii.mii_name));
+            miis.emplace(combobox->count(), mii);
+            combobox->addItem(QString::fromStdU16String(name));
+        }
+        saved_miis_offset += sizeof(mii);
+    }
+
+    if (miis.empty()) {
+        ShowNoMiis();
+        return;
+    }
+
+    if (combobox->count() > static_cast<int>(config.initially_selected_mii_index)) {
+        combobox->setCurrentIndex(static_cast<int>(config.initially_selected_mii_index));
+    }
+
+    connect(buttons, &QDialogButtonBox::accepted, this, [this] { accept(); });
+    connect(buttons, &QDialogButtonBox::rejected, this, [this] {
+        return_code = 1;
+        accept();
+    });
+    layout->addWidget(combobox);
+    layout->addWidget(buttons);
+    setLayout(layout);
+}
+
+void QtMiiSelectorDialog::ShowNoMiis() {
+    Frontend::MiiSelectorConfig config = mii_selector->config;
+    QMessageBox::StandardButton answer = QMessageBox::question(
+        nullptr,
+        config.title.empty() ? tr("Mii Selector") : QString::fromStdU16String(config.title),
+        tr("You don't have any Miis.\nUse standard Mii?"), QMessageBox::Yes | QMessageBox::No);
+
+    if (answer == QMessageBox::No)
+        return_code = 1;
+
+    QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
+}
+
+QtMiiSelector::QtMiiSelector(QWidget& parent_) : parent(parent_) {}
+
+void QtMiiSelector::Setup(const Frontend::MiiSelectorConfig* config) {
+    MiiSelector::Setup(config);
+    QMetaObject::invokeMethod(this, "OpenDialog", Qt::BlockingQueuedConnection);
+}
+
+void QtMiiSelector::OpenDialog() {
+    QtMiiSelectorDialog dialog(&parent, this);
+    dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+                          Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
+    dialog.setWindowModality(Qt::WindowModal);
+    dialog.exec();
+
+    int index = dialog.combobox->currentIndex();
+    LOG_INFO(Frontend, "Mii Selector dialog finished (return_code={}, index={})",
+             dialog.return_code, index);
+
+    HLE::Applets::MiiData mii_data =
+        index == -1 ? HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data
+                    : dialog.miis.at(dialog.combobox->currentIndex());
+    Finalize(dialog.return_code, dialog.return_code == 0 ? mii_data : HLE::Applets::MiiData{});
+}
diff --git a/src/citra_qt/applets/mii_selector.h b/src/citra_qt/applets/mii_selector.h
new file mode 100644
index 000000000..3135b35fb
--- /dev/null
+++ b/src/citra_qt/applets/mii_selector.h
@@ -0,0 +1,48 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <unordered_map>
+#include <QDialog>
+#include "core/frontend/applets/mii_selector.h"
+
+class QDialogButtonBox;
+class QComboBox;
+class QVBoxLayout;
+class QtMiiSelector;
+
+class QtMiiSelectorDialog final : public QDialog {
+    Q_OBJECT
+
+public:
+    QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_selector_);
+
+private:
+    void ShowNoMiis();
+
+    QDialogButtonBox* buttons;
+    QComboBox* combobox;
+    QVBoxLayout* layout;
+    QtMiiSelector* mii_selector;
+    u32 return_code = 0;
+    std::unordered_map<int, HLE::Applets::MiiData> miis;
+
+    friend class QtMiiSelector;
+};
+
+class QtMiiSelector final : public QObject, public Frontend::MiiSelector {
+    Q_OBJECT
+
+public:
+    explicit QtMiiSelector(QWidget& parent);
+    void Setup(const Frontend::MiiSelectorConfig* config) override;
+
+private:
+    Q_INVOKABLE void OpenDialog();
+
+    QWidget& parent;
+
+    friend class QtMiiSelectorDialog;
+};
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index d0a3a3720..e54bdfb85 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -16,6 +16,7 @@
 #include <QtWidgets>
 #include <fmt/format.h>
 #include "citra_qt/aboutdialog.h"
+#include "citra_qt/applets/mii_selector.h"
 #include "citra_qt/applets/swkbd.h"
 #include "citra_qt/bootmanager.h"
 #include "citra_qt/camera/qt_multimedia_camera.h"
@@ -1896,6 +1897,7 @@ int main(int argc, char* argv[]) {
 
     // Register frontend applets
     Frontend::RegisterDefaultApplets();
+    Frontend::RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
     Frontend::RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
 
     main_window.show();
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b70ef57be..633c9296b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -84,6 +84,8 @@ add_library(core STATIC
     file_sys/title_metadata.h
     frontend/applets/default_applets.cpp
     frontend/applets/default_applets.h
+    frontend/applets/mii_selector.cpp
+    frontend/applets/mii_selector.h
     frontend/applets/swkbd.cpp
     frontend/applets/swkbd.h
     frontend/camera/blank_camera.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index a72c8a1e9..2696118e2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -276,6 +276,10 @@ const Cheats::CheatEngine& System::CheatEngine() const {
     return *cheat_engine;
 }
 
+void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) {
+    registered_mii_selector = std::move(mii_selector);
+}
+
 void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd) {
     registered_swkbd = std::move(swkbd);
 }
diff --git a/src/core/core.h b/src/core/core.h
index 2e0c9ce7f..44e6ea796 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 #include "common/common_types.h"
+#include "core/frontend/applets/mii_selector.h"
 #include "core/frontend/applets/swkbd.h"
 #include "core/loader/loader.h"
 #include "core/memory.h"
@@ -222,8 +223,14 @@ public:
 
     /// Frontend Applets
 
+    void RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector);
+
     void RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd);
 
+    std::shared_ptr<Frontend::MiiSelector> GetMiiSelector() const {
+        return registered_mii_selector;
+    }
+
     std::shared_ptr<Frontend::SoftwareKeyboard> GetSoftwareKeyboard() const {
         return registered_swkbd;
     }
@@ -260,6 +267,7 @@ private:
     std::shared_ptr<Service::SM::ServiceManager> service_manager;
 
     /// Frontend applets
+    std::shared_ptr<Frontend::MiiSelector> registered_mii_selector;
     std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd;
 
     /// Cheats manager
diff --git a/src/core/frontend/applets/default_applets.cpp b/src/core/frontend/applets/default_applets.cpp
index 814b6381e..8fb07484c 100644
--- a/src/core/frontend/applets/default_applets.cpp
+++ b/src/core/frontend/applets/default_applets.cpp
@@ -3,10 +3,12 @@
 // Refer to the license.txt file included.
 
 #include "core/frontend/applets/default_applets.h"
+#include "core/frontend/applets/mii_selector.h"
 #include "core/frontend/applets/swkbd.h"
 
 namespace Frontend {
 void RegisterDefaultApplets() {
     RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
+    RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
 }
 } // namespace Frontend
diff --git a/src/core/frontend/applets/mii_selector.cpp b/src/core/frontend/applets/mii_selector.cpp
new file mode 100644
index 000000000..ca3978869
--- /dev/null
+++ b/src/core/frontend/applets/mii_selector.cpp
@@ -0,0 +1,27 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/core.h"
+#include "core/frontend/applets/mii_selector.h"
+
+namespace Frontend {
+
+void MiiSelector::Finalize(u32 return_code, HLE::Applets::MiiData mii) {
+    data = {return_code, mii};
+}
+
+void DefaultMiiSelector::Setup(const Frontend::MiiSelectorConfig* config) {
+    MiiSelector::Setup(config);
+    Finalize(0, HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data);
+}
+
+void RegisterMiiSelector(std::shared_ptr<MiiSelector> applet) {
+    Core::System::GetInstance().RegisterMiiSelector(applet);
+}
+
+std::shared_ptr<MiiSelector> GetRegisteredMiiSelector() {
+    return Core::System::GetInstance().GetMiiSelector();
+}
+
+} // namespace Frontend
diff --git a/src/core/frontend/applets/mii_selector.h b/src/core/frontend/applets/mii_selector.h
new file mode 100644
index 000000000..2913c2040
--- /dev/null
+++ b/src/core/frontend/applets/mii_selector.h
@@ -0,0 +1,56 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <memory>
+#include <string>
+#include "core/hle/applets/mii_selector.h"
+
+namespace Frontend {
+
+/// Configuration that's relevant to frontend implementation of applet. Anything missing that we
+/// later learn is needed can be added here and filled in by the backend HLE applet
+struct MiiSelectorConfig {
+    bool enable_cancel_button;
+    std::u16string title;
+    u32 initially_selected_mii_index;
+};
+
+struct MiiSelectorData {
+    u32 return_code;
+    HLE::Applets::MiiData mii;
+};
+
+class MiiSelector {
+public:
+    virtual void Setup(const MiiSelectorConfig* config) {
+        this->config = MiiSelectorConfig(*config);
+    }
+    const MiiSelectorData* ReceiveData() {
+        return &data;
+    }
+
+    /**
+     * Stores the data so that the HLE applet in core can
+     * send this to the calling application
+     */
+    void Finalize(u32 return_code, HLE::Applets::MiiData mii);
+
+protected:
+    MiiSelectorConfig config;
+    MiiSelectorData data;
+};
+
+class DefaultMiiSelector final : public MiiSelector {
+public:
+    void Setup(const MiiSelectorConfig* config) override;
+};
+
+void RegisterMiiSelector(std::shared_ptr<MiiSelector> applet);
+
+std::shared_ptr<MiiSelector> GetRegisteredMiiSelector();
+
+} // namespace Frontend
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 58311902d..1cfa6ea1c 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -4,10 +4,12 @@
 
 #include <cstring>
 #include <string>
+#include <boost/crc.hpp>
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
 #include "core/core.h"
+#include "core/frontend/applets/mii_selector.h"
 #include "core/hle/applets/mii_selector.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/shared_memory.h"
@@ -52,12 +54,51 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
 }
 
 ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
-    is_running = true;
-
-    // TODO(Subv): Reverse the parameter format for the Mii Selector
+    ASSERT_MSG(parameter.buffer.size() == sizeof(config),
+               "The size of the parameter (MiiConfig) is wrong");
 
     memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
 
+    using namespace Frontend;
+    frontend_applet = GetRegisteredMiiSelector();
+    if (frontend_applet) {
+        MiiSelectorConfig frontend_config = ToFrontendConfig(config);
+        frontend_applet->Setup(&frontend_config);
+    }
+
+    is_running = true;
+    return RESULT_SUCCESS;
+}
+
+void MiiSelector::Update() {
+    using namespace Frontend;
+    const MiiSelectorData* data = frontend_applet->ReceiveData();
+    result.return_code = data->return_code;
+    result.selected_mii_data = data->mii;
+    // Calculate the checksum of the selected Mii, see https://www.3dbrew.org/wiki/Mii#Checksum
+    result.mii_data_checksum = boost::crc<16, 0x1021, 0, 0, false, false>(
+        &result.selected_mii_data, sizeof(HLE::Applets::MiiData) + sizeof(result.unknown1));
+    result.selected_guest_mii_index = 0xFFFFFFFF;
+
+    // TODO(Subv): We're finalizing the applet immediately after it's started,
+    // but we should defer this call until after all the input has been collected.
+    Finalize();
+}
+
+void MiiSelector::Finalize() {
+    // Let the application know that we're closing
+    Service::APT::MessageParameter message;
+    message.buffer.resize(sizeof(MiiResult));
+    std::memcpy(message.buffer.data(), &result, message.buffer.size());
+    message.signal = Service::APT::SignalType::WakeupByExit;
+    message.destination_id = Service::APT::AppletId::Application;
+    message.sender_id = id;
+    SendParameter(message);
+
+    is_running = false;
+}
+
+MiiResult MiiSelector::GetStandardMiiResult() {
     // This data was obtained by writing the returned buffer in AppletManager::GlanceParameter of
     // the LLEd Mii picker of version system version 11.8.0 to a file and then matching the values
     // to the members of the MiiResult struct
@@ -95,18 +136,14 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
     result.mii_data_checksum = 0x056C;
     result.guest_mii_name.fill(0x0);
 
-    // Let the application know that we're closing
-    Service::APT::MessageParameter message;
-    message.buffer.resize(sizeof(MiiResult));
-    std::memcpy(message.buffer.data(), &result, message.buffer.size());
-    message.signal = Service::APT::SignalType::WakeupByExit;
-    message.destination_id = Service::APT::AppletId::Application;
-    message.sender_id = id;
-    SendParameter(message);
-
-    is_running = false;
-    return RESULT_SUCCESS;
+    return result;
 }
 
-void MiiSelector::Update() {}
+Frontend::MiiSelectorConfig MiiSelector::ToFrontendConfig(const MiiConfig& config) const {
+    Frontend::MiiSelectorConfig frontend_config;
+    frontend_config.enable_cancel_button = config.enable_cancel_button == 1;
+    frontend_config.title = reinterpret_cast<const char16_t*>(config.title.data());
+    frontend_config.initially_selected_mii_index = config.initially_selected_mii_index;
+    return frontend_config;
+}
 } // namespace HLE::Applets
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index c4a7dae19..d25f972a1 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -12,6 +12,11 @@
 #include "core/hle/result.h"
 #include "core/hle/service/apt/apt.h"
 
+namespace Frontend {
+class MiiSelector;
+struct MiiSelectorConfig;
+} // namespace Frontend
+
 namespace HLE::Applets {
 
 struct MiiConfig {
@@ -19,13 +24,13 @@ struct MiiConfig {
     u8 enable_guest_mii;
     u8 show_on_top_screen;
     INSERT_PADDING_BYTES(5);
-    u16 title[0x40];
+    std::array<u16, 0x40> title;
     INSERT_PADDING_BYTES(4);
     u8 show_guest_miis;
     INSERT_PADDING_BYTES(3);
     u32 initially_selected_mii_index;
-    u8 guest_mii_whitelist[6];
-    u8 user_mii_whitelist[0x64];
+    std::array<u8, 0x6> guest_mii_whitelist;
+    std::array<u8, 0x64> user_mii_whitelist;
     INSERT_PADDING_BYTES(2);
     u32 magic_value;
 };
@@ -117,12 +122,26 @@ public:
     ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
     void Update() override;
 
+    /**
+     * Sends the LibAppletClosing signal to the application,
+     * along with the relevant data buffers.
+     */
+    void Finalize();
+
+    static MiiResult GetStandardMiiResult();
+
 private:
+    Frontend::MiiSelectorConfig ToFrontendConfig(const MiiConfig& config) const;
+
     /// This SharedMemory will be created when we receive the LibAppJustStarted message.
     /// It holds the framebuffer info retrieved by the application with
     /// GSPGPU::ImportDisplayCaptureInfo
     std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
 
     MiiConfig config;
+
+    MiiResult result{};
+
+    std::shared_ptr<Frontend::MiiSelector> frontend_applet;
 };
 } // namespace HLE::Applets

From 781d4b787a02552f4ef03059dd3d68c1a4f59c51 Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Fri, 15 Feb 2019 19:20:06 +0100
Subject: [PATCH 3/5] Address first batch of review comments

---
 src/citra_qt/applets/mii_selector.cpp         | 92 +++++++------------
 src/citra_qt/applets/mii_selector.h           |  8 +-
 src/citra_qt/applets/swkbd.cpp                | 16 ++--
 src/citra_qt/applets/swkbd.h                  |  2 +-
 src/citra_qt/main.cpp                         |  4 +-
 src/core/file_sys/archive_backend.h           |  3 +
 src/core/frontend/applets/default_applets.cpp |  5 +-
 src/core/frontend/applets/mii_selector.cpp    | 11 +--
 src/core/frontend/applets/mii_selector.h      | 20 ++--
 src/core/frontend/applets/swkbd.cpp           | 10 +-
 src/core/frontend/applets/swkbd.h             | 21 ++---
 src/core/hle/applets/mii_selector.cpp         | 16 ++--
 src/core/hle/applets/swkbd.cpp                | 12 +--
 src/core/hle/service/ptm/ptm.h                |  2 +-
 14 files changed, 91 insertions(+), 131 deletions(-)

diff --git a/src/citra_qt/applets/mii_selector.cpp b/src/citra_qt/applets/mii_selector.cpp
index 3b905eb33..811804ea5 100644
--- a/src/citra_qt/applets/mii_selector.cpp
+++ b/src/citra_qt/applets/mii_selector.cpp
@@ -11,66 +11,58 @@
 #include "common/file_util.h"
 #include "core/file_sys/archive_extsavedata.h"
 #include "core/file_sys/file_backend.h"
-#include "core/hle/applets/buttons.h"
 #include "core/hle/service/ptm/ptm.h"
 
 QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_selector_)
     : QDialog(parent), mii_selector(mii_selector_) {
-    Frontend::MiiSelectorConfig config = mii_selector->config;
+    using namespace Frontend;
+    const auto config = mii_selector->config;
     layout = new QVBoxLayout;
     combobox = new QComboBox;
     buttons = new QDialogButtonBox;
     // Initialize buttons
-    buttons->addButton(tr(AppletButton::Ok), QDialogButtonBox::ButtonRole::AcceptRole);
+    buttons->addButton(tr(MII_BUTTON_OKAY), QDialogButtonBox::ButtonRole::AcceptRole);
     if (config.enable_cancel_button) {
-        buttons->addButton(tr(AppletButton::Cancel), QDialogButtonBox::ButtonRole::RejectRole);
+        buttons->addButton(tr(MII_BUTTON_CANCEL), QDialogButtonBox::ButtonRole::RejectRole);
     }
 
     setWindowTitle(config.title.empty() ? tr("Mii Selector")
                                         : QString::fromStdU16String(config.title));
 
+    miis.push_back(HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data);
+    combobox->addItem(tr("Standard Mii"));
+
     std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)};
     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
 
     auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id);
-    if (!archive_result.Succeeded()) {
-        ShowNoMiis();
-        return;
-    }
+    if (archive_result.Succeeded()) {
+        auto archive = std::move(archive_result).Unwrap();
 
-    auto archive = std::move(archive_result).Unwrap();
+        FileSys::Path file_path = "/CFL_DB.dat";
+        FileSys::Mode mode{};
+        mode.read_flag.Assign(1);
 
-    FileSys::Path file_path = "/CFL_DB.dat";
-    FileSys::Mode mode{};
-    mode.read_flag.Assign(1);
+        auto file_result = archive->OpenFile(file_path, mode);
+        if (file_result.Succeeded()) {
+            auto file = std::move(file_result).Unwrap();
 
-    auto file_result = archive->OpenFile(file_path, mode);
-    if (!file_result.Succeeded()) {
-        ShowNoMiis();
-        return;
-    }
-
-    auto file = std::move(file_result).Unwrap();
-
-    u32 saved_miis_offset = 0x8;
-    // The Mii Maker has a 100 Mii limit on the 3ds
-    for (int i = 0; i < 100; ++i) {
-        HLE::Applets::MiiData mii;
-        std::array<u8, sizeof(mii)> mii_raw;
-        file->Read(saved_miis_offset, sizeof(mii), mii_raw.data());
-        std::memcpy(&mii, mii_raw.data(), sizeof(mii));
-        if (mii.mii_id != 0) {
-            std::u16string name(sizeof(mii.mii_name), '\0');
-            std::memcpy(&name[0], mii.mii_name.data(), sizeof(mii.mii_name));
-            miis.emplace(combobox->count(), mii);
-            combobox->addItem(QString::fromStdU16String(name));
+            u32 saved_miis_offset = 0x8;
+            // The Mii Maker has a 100 Mii limit on the 3ds
+            for (int i = 0; i < 100; ++i) {
+                HLE::Applets::MiiData mii;
+                std::array<u8, sizeof(mii)> mii_raw;
+                file->Read(saved_miis_offset, sizeof(mii), mii_raw.data());
+                std::memcpy(&mii, mii_raw.data(), sizeof(mii));
+                if (mii.mii_id != 0) {
+                    std::u16string name(sizeof(mii.mii_name), '\0');
+                    std::memcpy(name.data(), mii.mii_name.data(), sizeof(mii.mii_name));
+                    miis.push_back(mii);
+                    combobox->addItem(QString::fromStdU16String(name));
+                }
+                saved_miis_offset += sizeof(mii);
+            }
         }
-        saved_miis_offset += sizeof(mii);
-    }
-
-    if (miis.empty()) {
-        ShowNoMiis();
-        return;
     }
 
     if (combobox->count() > static_cast<int>(config.initially_selected_mii_index)) {
@@ -87,22 +79,9 @@ QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_sel
     setLayout(layout);
 }
 
-void QtMiiSelectorDialog::ShowNoMiis() {
-    Frontend::MiiSelectorConfig config = mii_selector->config;
-    QMessageBox::StandardButton answer = QMessageBox::question(
-        nullptr,
-        config.title.empty() ? tr("Mii Selector") : QString::fromStdU16String(config.title),
-        tr("You don't have any Miis.\nUse standard Mii?"), QMessageBox::Yes | QMessageBox::No);
-
-    if (answer == QMessageBox::No)
-        return_code = 1;
-
-    QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
-}
-
 QtMiiSelector::QtMiiSelector(QWidget& parent_) : parent(parent_) {}
 
-void QtMiiSelector::Setup(const Frontend::MiiSelectorConfig* config) {
+void QtMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
     MiiSelector::Setup(config);
     QMetaObject::invokeMethod(this, "OpenDialog", Qt::BlockingQueuedConnection);
 }
@@ -114,12 +93,11 @@ void QtMiiSelector::OpenDialog() {
     dialog.setWindowModality(Qt::WindowModal);
     dialog.exec();
 
-    int index = dialog.combobox->currentIndex();
+    const auto index = dialog.combobox->currentIndex();
     LOG_INFO(Frontend, "Mii Selector dialog finished (return_code={}, index={})",
              dialog.return_code, index);
 
-    HLE::Applets::MiiData mii_data =
-        index == -1 ? HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data
-                    : dialog.miis.at(dialog.combobox->currentIndex());
-    Finalize(dialog.return_code, dialog.return_code == 0 ? mii_data : HLE::Applets::MiiData{});
+    const auto mii_data = dialog.miis.at(index);
+    Finalize(dialog.return_code,
+             dialog.return_code == 0 ? std::move(mii_data) : HLE::Applets::MiiData{});
 }
diff --git a/src/citra_qt/applets/mii_selector.h b/src/citra_qt/applets/mii_selector.h
index 3135b35fb..c3b6eabb2 100644
--- a/src/citra_qt/applets/mii_selector.h
+++ b/src/citra_qt/applets/mii_selector.h
@@ -8,8 +8,8 @@
 #include <QDialog>
 #include "core/frontend/applets/mii_selector.h"
 
-class QDialogButtonBox;
 class QComboBox;
+class QDialogButtonBox;
 class QVBoxLayout;
 class QtMiiSelector;
 
@@ -20,14 +20,12 @@ public:
     QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_selector_);
 
 private:
-    void ShowNoMiis();
-
     QDialogButtonBox* buttons;
     QComboBox* combobox;
     QVBoxLayout* layout;
     QtMiiSelector* mii_selector;
     u32 return_code = 0;
-    std::unordered_map<int, HLE::Applets::MiiData> miis;
+    std::vector<HLE::Applets::MiiData> miis;
 
     friend class QtMiiSelector;
 };
@@ -37,7 +35,7 @@ class QtMiiSelector final : public QObject, public Frontend::MiiSelector {
 
 public:
     explicit QtMiiSelector(QWidget& parent);
-    void Setup(const Frontend::MiiSelectorConfig* config) override;
+    void Setup(const Frontend::MiiSelectorConfig& config) override;
 
 private:
     Q_INVOKABLE void OpenDialog();
diff --git a/src/citra_qt/applets/swkbd.cpp b/src/citra_qt/applets/swkbd.cpp
index a9237389a..7514524b3 100644
--- a/src/citra_qt/applets/swkbd.cpp
+++ b/src/citra_qt/applets/swkbd.cpp
@@ -25,7 +25,7 @@ QtKeyboardValidator::State QtKeyboardValidator::validate(QString& input, int& po
 QtKeyboardDialog::QtKeyboardDialog(QWidget* parent, QtKeyboard* keyboard_)
     : QDialog(parent), keyboard(keyboard_) {
     using namespace Frontend;
-    KeyboardConfig config = keyboard->config;
+    const auto config = keyboard->config;
     layout = new QVBoxLayout;
     label = new QLabel(QString::fromStdString(config.hint_text));
     line_edit = new QLineEdit;
@@ -36,31 +36,31 @@ QtKeyboardDialog::QtKeyboardDialog(QWidget* parent, QtKeyboard* keyboard_)
     case ButtonConfig::Triple:
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[2])
-                               : tr(BUTTON_OKAY),
+                               : tr(SWKBD_BUTTON_OKAY),
                            QDialogButtonBox::ButtonRole::AcceptRole);
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[1])
-                               : tr(BUTTON_FORGOT),
+                               : tr(SWKBD_BUTTON_FORGOT),
                            QDialogButtonBox::ButtonRole::HelpRole);
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[0])
-                               : tr(BUTTON_CANCEL),
+                               : tr(SWKBD_BUTTON_CANCEL),
                            QDialogButtonBox::ButtonRole::RejectRole);
         break;
     case ButtonConfig::Dual:
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[1])
-                               : tr(BUTTON_OKAY),
+                               : tr(SWKBD_BUTTON_OKAY),
                            QDialogButtonBox::ButtonRole::AcceptRole);
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[0])
-                               : tr(BUTTON_CANCEL),
+                               : tr(SWKBD_BUTTON_CANCEL),
                            QDialogButtonBox::ButtonRole::RejectRole);
         break;
     case ButtonConfig::Single:
         buttons->addButton(config.has_custom_button_text
                                ? QString::fromStdString(config.button_text[0])
-                               : tr(BUTTON_OKAY),
+                               : tr(SWKBD_BUTTON_OKAY),
                            QDialogButtonBox::ButtonRole::AcceptRole);
         break;
     case ButtonConfig::None:
@@ -109,7 +109,7 @@ void QtKeyboardDialog::HandleValidationError(Frontend::ValidationError error) {
 
 QtKeyboard::QtKeyboard(QWidget& parent_) : parent(parent_) {}
 
-void QtKeyboard::Setup(const Frontend::KeyboardConfig* config) {
+void QtKeyboard::Setup(const Frontend::KeyboardConfig& config) {
     SoftwareKeyboard::Setup(config);
     if (this->config.button_config != Frontend::ButtonConfig::None) {
         ok_id = static_cast<u8>(this->config.button_config);
diff --git a/src/citra_qt/applets/swkbd.h b/src/citra_qt/applets/swkbd.h
index cfcbcb45e..5fcbd7112 100644
--- a/src/citra_qt/applets/swkbd.h
+++ b/src/citra_qt/applets/swkbd.h
@@ -48,7 +48,7 @@ class QtKeyboard final : public QObject, public Frontend::SoftwareKeyboard {
 
 public:
     explicit QtKeyboard(QWidget& parent);
-    void Setup(const Frontend::KeyboardConfig* config) override;
+    void Setup(const Frontend::KeyboardConfig& config) override;
 
 private:
     Q_INVOKABLE void OpenInputDialog();
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index e54bdfb85..f3d1d6582 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -1897,8 +1897,8 @@ int main(int argc, char* argv[]) {
 
     // Register frontend applets
     Frontend::RegisterDefaultApplets();
-    Frontend::RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
-    Frontend::RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
+    Core::System::GetInstance().RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
+    Core::System::GetInstance().RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
 
     main_window.show();
     int result = app.exec();
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 259ece84a..da05fcb7b 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -40,6 +40,9 @@ public:
     Path() : type(LowPathType::Invalid) {}
     Path(const char* path) : type(LowPathType::Char), string(path) {}
     Path(std::vector<u8> binary_data) : type(LowPathType::Binary), binary(std::move(binary_data)) {}
+    template <std::size_t size>
+    Path(std::array<u8, size> binary_data)
+        : type(LowPathType::Binary), binary(binary_data.begin(), binary_data.end()) {}
     Path(LowPathType type, const std::vector<u8>& data);
 
     LowPathType GetType() const {
diff --git a/src/core/frontend/applets/default_applets.cpp b/src/core/frontend/applets/default_applets.cpp
index 8fb07484c..38a6c48dd 100644
--- a/src/core/frontend/applets/default_applets.cpp
+++ b/src/core/frontend/applets/default_applets.cpp
@@ -2,13 +2,14 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include "core/core.h"
 #include "core/frontend/applets/default_applets.h"
 #include "core/frontend/applets/mii_selector.h"
 #include "core/frontend/applets/swkbd.h"
 
 namespace Frontend {
 void RegisterDefaultApplets() {
-    RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
-    RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
+    Core::System::GetInstance().RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
+    Core::System::GetInstance().RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
 }
 } // namespace Frontend
diff --git a/src/core/frontend/applets/mii_selector.cpp b/src/core/frontend/applets/mii_selector.cpp
index ca3978869..2ca23f1db 100644
--- a/src/core/frontend/applets/mii_selector.cpp
+++ b/src/core/frontend/applets/mii_selector.cpp
@@ -2,7 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/core.h"
 #include "core/frontend/applets/mii_selector.h"
 
 namespace Frontend {
@@ -11,17 +10,9 @@ void MiiSelector::Finalize(u32 return_code, HLE::Applets::MiiData mii) {
     data = {return_code, mii};
 }
 
-void DefaultMiiSelector::Setup(const Frontend::MiiSelectorConfig* config) {
+void DefaultMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
     MiiSelector::Setup(config);
     Finalize(0, HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data);
 }
 
-void RegisterMiiSelector(std::shared_ptr<MiiSelector> applet) {
-    Core::System::GetInstance().RegisterMiiSelector(applet);
-}
-
-std::shared_ptr<MiiSelector> GetRegisteredMiiSelector() {
-    return Core::System::GetInstance().GetMiiSelector();
-}
-
 } // namespace Frontend
diff --git a/src/core/frontend/applets/mii_selector.h b/src/core/frontend/applets/mii_selector.h
index 2913c2040..8cb59d9d2 100644
--- a/src/core/frontend/applets/mii_selector.h
+++ b/src/core/frontend/applets/mii_selector.h
@@ -4,13 +4,16 @@
 
 #pragma once
 
-#include <array>
 #include <memory>
 #include <string>
 #include "core/hle/applets/mii_selector.h"
 
 namespace Frontend {
 
+/// Default English button text mappings. Frontends may need to copy this to internationalize it.
+constexpr char MII_BUTTON_OKAY[] = "Ok";
+constexpr char MII_BUTTON_CANCEL[] = "Cancel";
+
 /// Configuration that's relevant to frontend implementation of applet. Anything missing that we
 /// later learn is needed can be added here and filled in by the backend HLE applet
 struct MiiSelectorConfig {
@@ -26,11 +29,12 @@ struct MiiSelectorData {
 
 class MiiSelector {
 public:
-    virtual void Setup(const MiiSelectorConfig* config) {
-        this->config = MiiSelectorConfig(*config);
+    virtual void Setup(const MiiSelectorConfig& config) {
+        this->config = MiiSelectorConfig(config);
     }
-    const MiiSelectorData* ReceiveData() {
-        return &data;
+
+    const MiiSelectorData& ReceiveData() const {
+        return data;
     }
 
     /**
@@ -46,11 +50,7 @@ protected:
 
 class DefaultMiiSelector final : public MiiSelector {
 public:
-    void Setup(const MiiSelectorConfig* config) override;
+    void Setup(const MiiSelectorConfig& config) override;
 };
 
-void RegisterMiiSelector(std::shared_ptr<MiiSelector> applet);
-
-std::shared_ptr<MiiSelector> GetRegisteredMiiSelector();
-
 } // namespace Frontend
diff --git a/src/core/frontend/applets/swkbd.cpp b/src/core/frontend/applets/swkbd.cpp
index 6c7442913..d1513e20c 100644
--- a/src/core/frontend/applets/swkbd.cpp
+++ b/src/core/frontend/applets/swkbd.cpp
@@ -135,7 +135,7 @@ ValidationError SoftwareKeyboard::Finalize(const std::string& text, u8 button) {
     return ValidationError::None;
 }
 
-void DefaultKeyboard::Setup(const Frontend::KeyboardConfig* config) {
+void DefaultKeyboard::Setup(const Frontend::KeyboardConfig& config) {
     SoftwareKeyboard::Setup(config);
 
     auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
@@ -157,12 +157,4 @@ void DefaultKeyboard::Setup(const Frontend::KeyboardConfig* config) {
     }
 }
 
-void RegisterSoftwareKeyboard(std::shared_ptr<SoftwareKeyboard> applet) {
-    Core::System::GetInstance().RegisterSoftwareKeyboard(applet);
-}
-
-std::shared_ptr<SoftwareKeyboard> GetRegisteredSoftwareKeyboard() {
-    return Core::System::GetInstance().GetSoftwareKeyboard();
-}
-
 } // namespace Frontend
diff --git a/src/core/frontend/applets/swkbd.h b/src/core/frontend/applets/swkbd.h
index 5c07eb12d..f678c0f48 100644
--- a/src/core/frontend/applets/swkbd.h
+++ b/src/core/frontend/applets/swkbd.h
@@ -30,9 +30,9 @@ enum class ButtonConfig {
 };
 
 /// Default English button text mappings. Frontends may need to copy this to internationalize it.
-constexpr char BUTTON_OKAY[] = "Ok";
-constexpr char BUTTON_CANCEL[] = "Cancel";
-constexpr char BUTTON_FORGOT[] = "I Forgot";
+constexpr char SWKBD_BUTTON_OKAY[] = "Ok";
+constexpr char SWKBD_BUTTON_CANCEL[] = "Cancel";
+constexpr char SWKBD_BUTTON_FORGOT[] = "I Forgot";
 
 /// Configuration thats relevent to frontend implementation of applets. Anything missing that we
 /// later learn is needed can be added here and filled in by the backend HLE applet
@@ -82,11 +82,12 @@ enum class ValidationError {
 
 class SoftwareKeyboard {
 public:
-    virtual void Setup(const KeyboardConfig* config) {
-        this->config = KeyboardConfig(*config);
+    virtual void Setup(const KeyboardConfig& config) {
+        this->config = KeyboardConfig(config);
     }
-    const KeyboardData* ReceiveData() {
-        return &data;
+
+    const KeyboardData& ReceiveData() const {
+        return data;
     }
 
     /**
@@ -121,11 +122,7 @@ protected:
 
 class DefaultKeyboard final : public SoftwareKeyboard {
 public:
-    void Setup(const KeyboardConfig* config) override;
+    void Setup(const KeyboardConfig& config) override;
 };
 
-void RegisterSoftwareKeyboard(std::shared_ptr<SoftwareKeyboard> applet);
-
-std::shared_ptr<SoftwareKeyboard> GetRegisteredSoftwareKeyboard();
-
 } // namespace Frontend
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 1cfa6ea1c..c606c95f8 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -60,11 +60,11 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
     memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
 
     using namespace Frontend;
-    frontend_applet = GetRegisteredMiiSelector();
-    if (frontend_applet) {
-        MiiSelectorConfig frontend_config = ToFrontendConfig(config);
-        frontend_applet->Setup(&frontend_config);
-    }
+    frontend_applet = Core::System::GetInstance().GetMiiSelector();
+    ASSERT(frontend_applet);
+
+    MiiSelectorConfig frontend_config = ToFrontendConfig(config);
+    frontend_applet->Setup(frontend_config);
 
     is_running = true;
     return RESULT_SUCCESS;
@@ -72,9 +72,9 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
 
 void MiiSelector::Update() {
     using namespace Frontend;
-    const MiiSelectorData* data = frontend_applet->ReceiveData();
-    result.return_code = data->return_code;
-    result.selected_mii_data = data->mii;
+    const MiiSelectorData& data = frontend_applet->ReceiveData();
+    result.return_code = data.return_code;
+    result.selected_mii_data = data.mii;
     // Calculate the checksum of the selected Mii, see https://www.3dbrew.org/wiki/Mii#Checksum
     result.mii_data_checksum = boost::crc<16, 0x1021, 0, 0, false, false>(
         &result.selected_mii_data, sizeof(HLE::Applets::MiiData) + sizeof(result.unknown1));
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index 3f209e9f4..4e4dd1b90 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -68,11 +68,11 @@ ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter cons
     DrawScreenKeyboard();
 
     using namespace Frontend;
-    frontend_applet = GetRegisteredSoftwareKeyboard();
-    if (frontend_applet) {
-        KeyboardConfig frontend_config = ToFrontendConfig(config);
-        frontend_applet->Setup(&frontend_config);
-    }
+    frontend_applet = Core::System::GetInstance().GetSoftwareKeyboard();
+    ASSERT(frontend_applet);
+
+    KeyboardConfig frontend_config = ToFrontendConfig(config);
+    frontend_applet->Setup(frontend_config);
 
     is_running = true;
     return RESULT_SUCCESS;
@@ -80,7 +80,7 @@ ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter cons
 
 void SoftwareKeyboard::Update() {
     using namespace Frontend;
-    KeyboardData data(*frontend_applet->ReceiveData());
+    KeyboardData data(frontend_applet->ReceiveData());
     std::u16string text = Common::UTF8ToUTF16(data.text);
     memcpy(text_memory->GetPointer(), text.c_str(), text.length() * sizeof(char16_t));
     switch (config.num_buttons_m1) {
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index ee29eb2e8..549e69353 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -16,7 +16,7 @@ class System;
 namespace Service::PTM {
 
 /// Id of the SharedExtData archive used by the PTM process
-static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
+constexpr std::array<u8, 12> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
 
 /// Charge levels used by PTM functions
 enum class ChargeLevels : u32 {

From 1517d2fef79f674fd3cc5361e4ada369a69be963 Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Tue, 26 Feb 2019 23:36:58 +0100
Subject: [PATCH 4/5] Address more reviews

---
 src/citra_qt/applets/mii_selector.cpp | 7 ++++---
 src/core/hle/applets/mii_selector.cpp | 5 ++++-
 src/core/hle/applets/mii_selector.h   | 2 +-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/citra_qt/applets/mii_selector.cpp b/src/citra_qt/applets/mii_selector.cpp
index 811804ea5..c7723dd42 100644
--- a/src/citra_qt/applets/mii_selector.cpp
+++ b/src/citra_qt/applets/mii_selector.cpp
@@ -26,8 +26,9 @@ QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_sel
         buttons->addButton(tr(MII_BUTTON_CANCEL), QDialogButtonBox::ButtonRole::RejectRole);
     }
 
-    setWindowTitle(config.title.empty() ? tr("Mii Selector")
-                                        : QString::fromStdU16String(config.title));
+    setWindowTitle(config.title.empty() || config.title.at(0) == '\x0000'
+                       ? tr("Mii Selector")
+                       : QString::fromStdU16String(config.title));
 
     miis.push_back(HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data);
     combobox->addItem(tr("Standard Mii"));
@@ -35,7 +36,7 @@ QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_sel
     std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)};
     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true);
 
-    auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id);
+    auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id, 0);
     if (archive_result.Succeeded()) {
         auto archive = std::move(archive_result).Unwrap();
 
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index c606c95f8..cda28ffc3 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -142,7 +142,10 @@ MiiResult MiiSelector::GetStandardMiiResult() {
 Frontend::MiiSelectorConfig MiiSelector::ToFrontendConfig(const MiiConfig& config) const {
     Frontend::MiiSelectorConfig frontend_config;
     frontend_config.enable_cancel_button = config.enable_cancel_button == 1;
-    frontend_config.title = reinterpret_cast<const char16_t*>(config.title.data());
+    std::transform(config.title.begin(), config.title.end(),
+                   std::back_inserter(frontend_config.title), [](u16_le character) -> char16_t {
+                       return static_cast<char16_t>(static_cast<u16>(character));
+                   });
     frontend_config.initially_selected_mii_index = config.initially_selected_mii_index;
     return frontend_config;
 }
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index d25f972a1..0a8b8113c 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -24,7 +24,7 @@ struct MiiConfig {
     u8 enable_guest_mii;
     u8 show_on_top_screen;
     INSERT_PADDING_BYTES(5);
-    std::array<u16, 0x40> title;
+    std::array<u16_le, 0x40> title;
     INSERT_PADDING_BYTES(4);
     u8 show_guest_miis;
     INSERT_PADDING_BYTES(3);

From e9bd34f7da2feb9b8fca6fbc2c0844cad7929cbd Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Sun, 7 Apr 2019 15:58:42 +0200
Subject: [PATCH 5/5] Address remaining review comments

---
 src/citra_qt/applets/mii_selector.cpp    | 22 ++++++++++++++++++----
 src/core/file_sys/archive_backend.h      |  2 +-
 src/core/frontend/applets/mii_selector.h |  2 +-
 src/core/hle/applets/mii_selector.cpp    | 19 +++++++++++++++----
 4 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/src/citra_qt/applets/mii_selector.cpp b/src/citra_qt/applets/mii_selector.cpp
index c7723dd42..b51a33fb7 100644
--- a/src/citra_qt/applets/mii_selector.cpp
+++ b/src/citra_qt/applets/mii_selector.cpp
@@ -9,10 +9,25 @@
 #include <QVBoxLayout>
 #include "citra_qt/applets/mii_selector.h"
 #include "common/file_util.h"
+#include "common/string_util.h"
 #include "core/file_sys/archive_extsavedata.h"
 #include "core/file_sys/file_backend.h"
 #include "core/hle/service/ptm/ptm.h"
 
+/**
+ * Converts a UTF-16 text in a container to a UTF-8 std::string.
+ */
+template <typename T>
+std::string TextFromBuffer(const T& text) {
+    const auto text_end = std::find(text.begin(), text.end(), u'\0');
+    const std::size_t text_size = std::distance(text.begin(), text_end);
+    std::u16string buffer(text_size, 0);
+    std::transform(text.begin(), text_end, buffer.begin(), [](u16_le character) {
+        return static_cast<char16_t>(static_cast<u16>(character));
+    });
+    return Common::UTF16ToUTF8(buffer);
+}
+
 QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_selector_)
     : QDialog(parent), mii_selector(mii_selector_) {
     using namespace Frontend;
@@ -28,7 +43,7 @@ QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_sel
 
     setWindowTitle(config.title.empty() || config.title.at(0) == '\x0000'
                        ? tr("Mii Selector")
-                       : QString::fromStdU16String(config.title));
+                       : QString::fromStdString(config.title));
 
     miis.push_back(HLE::Applets::MiiSelector::GetStandardMiiResult().selected_mii_data);
     combobox->addItem(tr("Standard Mii"));
@@ -56,10 +71,9 @@ QtMiiSelectorDialog::QtMiiSelectorDialog(QWidget* parent, QtMiiSelector* mii_sel
                 file->Read(saved_miis_offset, sizeof(mii), mii_raw.data());
                 std::memcpy(&mii, mii_raw.data(), sizeof(mii));
                 if (mii.mii_id != 0) {
-                    std::u16string name(sizeof(mii.mii_name), '\0');
-                    std::memcpy(name.data(), mii.mii_name.data(), sizeof(mii.mii_name));
+                    std::string name = TextFromBuffer(mii.mii_name);
                     miis.push_back(mii);
-                    combobox->addItem(QString::fromStdU16String(name));
+                    combobox->addItem(QString::fromStdString(name));
                 }
                 saved_miis_offset += sizeof(mii);
             }
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index da05fcb7b..2df4f98c4 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -41,7 +41,7 @@ public:
     Path(const char* path) : type(LowPathType::Char), string(path) {}
     Path(std::vector<u8> binary_data) : type(LowPathType::Binary), binary(std::move(binary_data)) {}
     template <std::size_t size>
-    Path(std::array<u8, size> binary_data)
+    Path(const std::array<u8, size>& binary_data)
         : type(LowPathType::Binary), binary(binary_data.begin(), binary_data.end()) {}
     Path(LowPathType type, const std::vector<u8>& data);
 
diff --git a/src/core/frontend/applets/mii_selector.h b/src/core/frontend/applets/mii_selector.h
index 8cb59d9d2..588bc0c5b 100644
--- a/src/core/frontend/applets/mii_selector.h
+++ b/src/core/frontend/applets/mii_selector.h
@@ -18,7 +18,7 @@ constexpr char MII_BUTTON_CANCEL[] = "Cancel";
 /// later learn is needed can be added here and filled in by the backend HLE applet
 struct MiiSelectorConfig {
     bool enable_cancel_button;
-    std::u16string title;
+    std::string title;
     u32 initially_selected_mii_index;
 };
 
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index cda28ffc3..596e216c0 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -19,6 +19,20 @@
 
 namespace HLE::Applets {
 
+/**
+ * Converts a UTF-16 text in a container to a UTF-8 std::string.
+ */
+template <typename T>
+std::string TextFromBuffer(const T& text) {
+    const auto text_end = std::find(text.begin(), text.end(), u'\0');
+    const std::size_t text_size = std::distance(text.begin(), text_end);
+    std::u16string buffer(text_size, 0);
+    std::transform(text.begin(), text_end, buffer.begin(), [](u16_le character) {
+        return static_cast<char16_t>(static_cast<u16>(character));
+    });
+    return Common::UTF16ToUTF8(buffer);
+}
+
 ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
     if (parameter.signal != Service::APT::SignalType::Request) {
         LOG_ERROR(Service_APT, "unsupported signal {}", static_cast<u32>(parameter.signal));
@@ -142,10 +156,7 @@ MiiResult MiiSelector::GetStandardMiiResult() {
 Frontend::MiiSelectorConfig MiiSelector::ToFrontendConfig(const MiiConfig& config) const {
     Frontend::MiiSelectorConfig frontend_config;
     frontend_config.enable_cancel_button = config.enable_cancel_button == 1;
-    std::transform(config.title.begin(), config.title.end(),
-                   std::back_inserter(frontend_config.title), [](u16_le character) -> char16_t {
-                       return static_cast<char16_t>(static_cast<u16>(character));
-                   });
+    frontend_config.title = TextFromBuffer(config.title);
     frontend_config.initially_selected_mii_index = config.initially_selected_mii_index;
     return frontend_config;
 }