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