mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	applets: implement HLE mii selector applet
This commit is contained in:
		
							parent
							
								
									f903d3161d
								
							
						
					
					
						commit
						041638ea4d
					
				
					 12 changed files with 350 additions and 18 deletions
				
			
		| 
						 | 
					@ -10,6 +10,8 @@ add_executable(citra-qt
 | 
				
			||||||
    Info.plist
 | 
					    Info.plist
 | 
				
			||||||
    aboutdialog.cpp
 | 
					    aboutdialog.cpp
 | 
				
			||||||
    aboutdialog.h
 | 
					    aboutdialog.h
 | 
				
			||||||
 | 
					    applets/mii_selector.cpp
 | 
				
			||||||
 | 
					    applets/mii_selector.h
 | 
				
			||||||
    applets/swkbd.cpp
 | 
					    applets/swkbd.cpp
 | 
				
			||||||
    applets/swkbd.h
 | 
					    applets/swkbd.h
 | 
				
			||||||
    bootmanager.cpp
 | 
					    bootmanager.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										125
									
								
								src/citra_qt/applets/mii_selector.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/citra_qt/applets/mii_selector.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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{});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/citra_qt/applets/mii_selector.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/citra_qt/applets/mii_selector.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
#include <QtWidgets>
 | 
					#include <QtWidgets>
 | 
				
			||||||
#include <fmt/format.h>
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include "citra_qt/aboutdialog.h"
 | 
					#include "citra_qt/aboutdialog.h"
 | 
				
			||||||
 | 
					#include "citra_qt/applets/mii_selector.h"
 | 
				
			||||||
#include "citra_qt/applets/swkbd.h"
 | 
					#include "citra_qt/applets/swkbd.h"
 | 
				
			||||||
#include "citra_qt/bootmanager.h"
 | 
					#include "citra_qt/bootmanager.h"
 | 
				
			||||||
#include "citra_qt/camera/qt_multimedia_camera.h"
 | 
					#include "citra_qt/camera/qt_multimedia_camera.h"
 | 
				
			||||||
| 
						 | 
					@ -1896,6 +1897,7 @@ int main(int argc, char* argv[]) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Register frontend applets
 | 
					    // Register frontend applets
 | 
				
			||||||
    Frontend::RegisterDefaultApplets();
 | 
					    Frontend::RegisterDefaultApplets();
 | 
				
			||||||
 | 
					    Frontend::RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
 | 
				
			||||||
    Frontend::RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
 | 
					    Frontend::RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    main_window.show();
 | 
					    main_window.show();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,6 +84,8 @@ add_library(core STATIC
 | 
				
			||||||
    file_sys/title_metadata.h
 | 
					    file_sys/title_metadata.h
 | 
				
			||||||
    frontend/applets/default_applets.cpp
 | 
					    frontend/applets/default_applets.cpp
 | 
				
			||||||
    frontend/applets/default_applets.h
 | 
					    frontend/applets/default_applets.h
 | 
				
			||||||
 | 
					    frontend/applets/mii_selector.cpp
 | 
				
			||||||
 | 
					    frontend/applets/mii_selector.h
 | 
				
			||||||
    frontend/applets/swkbd.cpp
 | 
					    frontend/applets/swkbd.cpp
 | 
				
			||||||
    frontend/applets/swkbd.h
 | 
					    frontend/applets/swkbd.h
 | 
				
			||||||
    frontend/camera/blank_camera.cpp
 | 
					    frontend/camera/blank_camera.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,6 +276,10 @@ const Cheats::CheatEngine& System::CheatEngine() const {
 | 
				
			||||||
    return *cheat_engine;
 | 
					    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) {
 | 
					void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd) {
 | 
				
			||||||
    registered_swkbd = std::move(swkbd);
 | 
					    registered_swkbd = std::move(swkbd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include "common/common_types.h"
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					#include "core/frontend/applets/mii_selector.h"
 | 
				
			||||||
#include "core/frontend/applets/swkbd.h"
 | 
					#include "core/frontend/applets/swkbd.h"
 | 
				
			||||||
#include "core/loader/loader.h"
 | 
					#include "core/loader/loader.h"
 | 
				
			||||||
#include "core/memory.h"
 | 
					#include "core/memory.h"
 | 
				
			||||||
| 
						 | 
					@ -222,8 +223,14 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Frontend Applets
 | 
					    /// Frontend Applets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd);
 | 
					    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 {
 | 
					    std::shared_ptr<Frontend::SoftwareKeyboard> GetSoftwareKeyboard() const {
 | 
				
			||||||
        return registered_swkbd;
 | 
					        return registered_swkbd;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -260,6 +267,7 @@ private:
 | 
				
			||||||
    std::shared_ptr<Service::SM::ServiceManager> service_manager;
 | 
					    std::shared_ptr<Service::SM::ServiceManager> service_manager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Frontend applets
 | 
					    /// Frontend applets
 | 
				
			||||||
 | 
					    std::shared_ptr<Frontend::MiiSelector> registered_mii_selector;
 | 
				
			||||||
    std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd;
 | 
					    std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Cheats manager
 | 
					    /// Cheats manager
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,12 @@
 | 
				
			||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "core/frontend/applets/default_applets.h"
 | 
					#include "core/frontend/applets/default_applets.h"
 | 
				
			||||||
 | 
					#include "core/frontend/applets/mii_selector.h"
 | 
				
			||||||
#include "core/frontend/applets/swkbd.h"
 | 
					#include "core/frontend/applets/swkbd.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Frontend {
 | 
					namespace Frontend {
 | 
				
			||||||
void RegisterDefaultApplets() {
 | 
					void RegisterDefaultApplets() {
 | 
				
			||||||
    RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
 | 
					    RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
 | 
				
			||||||
 | 
					    RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
} // namespace Frontend
 | 
					} // namespace Frontend
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/core/frontend/applets/mii_selector.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/core/frontend/applets/mii_selector.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										56
									
								
								src/core/frontend/applets/mii_selector.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/core/frontend/applets/mii_selector.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -4,10 +4,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <boost/crc.hpp>
 | 
				
			||||||
#include "common/assert.h"
 | 
					#include "common/assert.h"
 | 
				
			||||||
#include "common/logging/log.h"
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
#include "common/string_util.h"
 | 
					#include "common/string_util.h"
 | 
				
			||||||
#include "core/core.h"
 | 
					#include "core/core.h"
 | 
				
			||||||
 | 
					#include "core/frontend/applets/mii_selector.h"
 | 
				
			||||||
#include "core/hle/applets/mii_selector.h"
 | 
					#include "core/hle/applets/mii_selector.h"
 | 
				
			||||||
#include "core/hle/kernel/kernel.h"
 | 
					#include "core/hle/kernel/kernel.h"
 | 
				
			||||||
#include "core/hle/kernel/shared_memory.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) {
 | 
					ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
 | 
				
			||||||
    is_running = true;
 | 
					    ASSERT_MSG(parameter.buffer.size() == sizeof(config),
 | 
				
			||||||
 | 
					               "The size of the parameter (MiiConfig) is wrong");
 | 
				
			||||||
    // TODO(Subv): Reverse the parameter format for the Mii Selector
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
 | 
					    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
 | 
					    // 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
 | 
					    // 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
 | 
					    // 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.mii_data_checksum = 0x056C;
 | 
				
			||||||
    result.guest_mii_name.fill(0x0);
 | 
					    result.guest_mii_name.fill(0x0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Let the application know that we're closing
 | 
					    return result;
 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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
 | 
					} // namespace HLE::Applets
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,11 @@
 | 
				
			||||||
#include "core/hle/result.h"
 | 
					#include "core/hle/result.h"
 | 
				
			||||||
#include "core/hle/service/apt/apt.h"
 | 
					#include "core/hle/service/apt/apt.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Frontend {
 | 
				
			||||||
 | 
					class MiiSelector;
 | 
				
			||||||
 | 
					struct MiiSelectorConfig;
 | 
				
			||||||
 | 
					} // namespace Frontend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace HLE::Applets {
 | 
					namespace HLE::Applets {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MiiConfig {
 | 
					struct MiiConfig {
 | 
				
			||||||
| 
						 | 
					@ -19,13 +24,13 @@ struct MiiConfig {
 | 
				
			||||||
    u8 enable_guest_mii;
 | 
					    u8 enable_guest_mii;
 | 
				
			||||||
    u8 show_on_top_screen;
 | 
					    u8 show_on_top_screen;
 | 
				
			||||||
    INSERT_PADDING_BYTES(5);
 | 
					    INSERT_PADDING_BYTES(5);
 | 
				
			||||||
    u16 title[0x40];
 | 
					    std::array<u16, 0x40> title;
 | 
				
			||||||
    INSERT_PADDING_BYTES(4);
 | 
					    INSERT_PADDING_BYTES(4);
 | 
				
			||||||
    u8 show_guest_miis;
 | 
					    u8 show_guest_miis;
 | 
				
			||||||
    INSERT_PADDING_BYTES(3);
 | 
					    INSERT_PADDING_BYTES(3);
 | 
				
			||||||
    u32 initially_selected_mii_index;
 | 
					    u32 initially_selected_mii_index;
 | 
				
			||||||
    u8 guest_mii_whitelist[6];
 | 
					    std::array<u8, 0x6> guest_mii_whitelist;
 | 
				
			||||||
    u8 user_mii_whitelist[0x64];
 | 
					    std::array<u8, 0x64> user_mii_whitelist;
 | 
				
			||||||
    INSERT_PADDING_BYTES(2);
 | 
					    INSERT_PADDING_BYTES(2);
 | 
				
			||||||
    u32 magic_value;
 | 
					    u32 magic_value;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -117,12 +122,26 @@ public:
 | 
				
			||||||
    ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
 | 
					    ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
 | 
				
			||||||
    void Update() override;
 | 
					    void Update() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sends the LibAppletClosing signal to the application,
 | 
				
			||||||
 | 
					     * along with the relevant data buffers.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static MiiResult GetStandardMiiResult();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					    Frontend::MiiSelectorConfig ToFrontendConfig(const MiiConfig& config) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// This SharedMemory will be created when we receive the LibAppJustStarted message.
 | 
					    /// This SharedMemory will be created when we receive the LibAppJustStarted message.
 | 
				
			||||||
    /// It holds the framebuffer info retrieved by the application with
 | 
					    /// It holds the framebuffer info retrieved by the application with
 | 
				
			||||||
    /// GSPGPU::ImportDisplayCaptureInfo
 | 
					    /// GSPGPU::ImportDisplayCaptureInfo
 | 
				
			||||||
    std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
 | 
					    std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MiiConfig config;
 | 
					    MiiConfig config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MiiResult result{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Frontend::MiiSelector> frontend_applet;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
} // namespace HLE::Applets
 | 
					} // namespace HLE::Applets
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue