From 6e6c84eebba714c8f21f9e5ae77a36a53f240079 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 25 Jan 2024 03:39:48 +0200 Subject: [PATCH] Add Mii Selector --- include/applets/applet.hpp | 2 +- include/applets/mii_selector.hpp | 72 +++++++++++++++++++++++++- include/applets/software_keyboard.hpp | 2 +- src/core/applets/mii_selector.cpp | 68 +++++++++++++++++++++++- src/core/applets/software_keyboard.cpp | 9 +++- src/core/services/apt.cpp | 8 +-- src/core/services/ptm.cpp | 2 +- 7 files changed, 150 insertions(+), 13 deletions(-) diff --git a/include/applets/applet.hpp b/include/applets/applet.hpp index d9ba6143..48f20b03 100644 --- a/include/applets/applet.hpp +++ b/include/applets/applet.hpp @@ -84,7 +84,7 @@ namespace Applets { virtual const char* name() = 0; // Called by APT::StartLibraryApplet and similar - virtual Result::HorizonResult start(const MemoryBlock& sharedMem, const std::vector& parameters, u32 appID) = 0; + virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector& parameters, u32 appID) = 0; // Transfer parameters from application -> applet virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0; virtual void reset() = 0; diff --git a/include/applets/mii_selector.hpp b/include/applets/mii_selector.hpp index 3b6cf2ec..36f9fe79 100644 --- a/include/applets/mii_selector.hpp +++ b/include/applets/mii_selector.hpp @@ -1,13 +1,83 @@ +#include + #include "applets/applet.hpp" +#include "swap.hpp" namespace Applets { + struct MiiConfig { + u8 enableCancelButton; + u8 enableGuestMii; + u8 showOnTopScreen; + std::array pad1; + std::array title; + std::array pad2; + u8 showGuestMiis; + std::array pad3; + u32 initiallySelectedIndex; + std::array guestMiiWhitelist; + std::array userMiiWhitelist; + std::array pad4; + u32 magicValue; + }; + static_assert(sizeof(MiiConfig) == 0x104, "Mii config size is wrong"); + + // Some members of this struct are not properly aligned so we need pragma pack +#pragma pack(push, 1) + struct MiiData { + u8 version; + u8 miiOptions; + u8 miiPos; + u8 consoleID; + + u64_be systemID; + u32_be miiID; + std::array creatorMAC; + u16 padding; + + u16_be miiDetails; + std::array miiName; + u8 height; + u8 width; + + u8 faceStyle; + u8 faceDetails; + u8 hairStyle; + u8 hairDetails; + u32_be eyeDetails; + u32_be eyebrowDetails; + u16_be noseDetails; + u16_be mouthDetails; + u16_be moustacheDetails; + u16_be beardDetails; + u16_be glassesDetails; + u16_be moleDetails; + + std::array authorName; + }; +#pragma pack(pop) + static_assert(sizeof(MiiData) == 0x5C, "MiiData structure has incorrect size"); + + struct MiiResult { + u32_be returnCode; + u32_be isGuestMiiSelected; + u32_be selectedGuestMiiIndex; + MiiData selectedMiiData; + u16_be unknown1; + u16_be miiChecksum; + std::array guestMiiName; + }; + static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); + class MiiSelectorApplet final : public AppletBase { public: virtual const char* name() override { return "Mii Selector"; } - virtual Result::HorizonResult start(const MemoryBlock& sharedMem, const std::vector& parameters, u32 appID) override; + virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector& parameters, u32 appID) override; virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override; virtual void reset() override; + MiiResult output; + MiiConfig config; + MiiResult getDefaultMii(); MiiSelectorApplet(Memory& memory, std::optional& nextParam) : AppletBase(memory, nextParam) {} }; } // namespace Applets \ No newline at end of file diff --git a/include/applets/software_keyboard.hpp b/include/applets/software_keyboard.hpp index 3a167ad0..f753566d 100644 --- a/include/applets/software_keyboard.hpp +++ b/include/applets/software_keyboard.hpp @@ -150,7 +150,7 @@ namespace Applets { static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software keyboard config size is wrong"); virtual const char* name() override { return "Software Keyboard"; } - virtual Result::HorizonResult start(const MemoryBlock& sharedMem, const std::vector& parameters, u32 appID) override; + virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector& parameters, u32 appID) override; virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override; virtual void reset() override; diff --git a/src/core/applets/mii_selector.cpp b/src/core/applets/mii_selector.cpp index ede8de28..5b7637e3 100644 --- a/src/core/applets/mii_selector.cpp +++ b/src/core/applets/mii_selector.cpp @@ -1,11 +1,38 @@ #include "applets/mii_selector.hpp" +#include +#include + #include "kernel/handles.hpp" using namespace Applets; void MiiSelectorApplet::reset() {} -Result::HorizonResult MiiSelectorApplet::start(const MemoryBlock& sharedMem, const std::vector& parameters, u32 appID) { return Result::Success; } +Result::HorizonResult MiiSelectorApplet::start(const MemoryBlock* sharedMem, const std::vector& parameters, u32 appID) { + // Get mii configuration from the application + std::memcpy(&config, ¶meters[0], sizeof(config)); + + Applets::Parameter param = Applets::Parameter{ + .senderID = appID, + .destID = AppletIDs::Application, + .signal = static_cast(APTSignal::WakeupByExit), + .object = 0, + }; + + // Thanks to Citra devs as always for the default mii data and other applet help + output = getDefaultMii(); + output.returnCode = 0; // Success + // output.selectedMiiData = miiData; + output.selectedGuestMiiIndex = std::numeric_limits::max(); + output.miiChecksum = boost::crc<16, 0x1021, 0, 0, false, false>(&output.selectedMiiData, sizeof(MiiData) + sizeof(output.unknown1)); + + // Copy output into the response parameter + param.data.resize(sizeof(output)); + std::memcpy(¶m.data[0], &output, sizeof(output)); + + nextParameter = param; + return Result::Success; +} Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Parameter& parameter) { Helpers::warn("Mii Selector: Unimplemented ReceiveParameter"); @@ -20,4 +47,43 @@ Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Paramet nextParameter = param; return Result::Success; +} + +MiiResult MiiSelectorApplet::getDefaultMii() { + // This data was obtained from Citra + MiiData miiData; + miiData.version = 0x03; + miiData.miiOptions = 0x00; + miiData.miiPos = 0x10; + miiData.consoleID = 0x30; + miiData.systemID = 0xD285B6B300C8850A; + miiData.miiID = 0x98391EE4; + miiData.creatorMAC = {0x40, 0xF4, 0x07, 0xB7, 0x37, 0x10}; + miiData.padding = 0x0000; + miiData.miiDetails = 0xA600; + miiData.miiName = {'P', 'a', 'n', 'd', 'a', '3', 'D', 'S', 0x0, 0x0}; + miiData.height = 0x40; + miiData.width = 0x40; + miiData.faceStyle = 0x00; + miiData.faceDetails = 0x00; + miiData.hairStyle = 0x21; + miiData.hairDetails = 0x01; + miiData.eyeDetails = 0x02684418; + miiData.eyebrowDetails = 0x26344614; + miiData.noseDetails = 0x8112; + miiData.mouthDetails = 0x1768; + miiData.moustacheDetails = 0x0D00; + miiData.beardDetails = 0x0029; + miiData.glassesDetails = 0x0052; + miiData.moleDetails = 0x4850; + miiData.authorName = {u'B', u'O', u'N', u'K', u'E', u'R'}; + + MiiResult result; + result.returnCode = 0x0; + result.isGuestMiiSelected = 0x0; + result.selectedGuestMiiIndex = std::numeric_limits::max(); + result.selectedMiiData = miiData; + result.guestMiiName.fill(0x0); + + return result; } \ No newline at end of file diff --git a/src/core/applets/software_keyboard.cpp b/src/core/applets/software_keyboard.cpp index dfe68b60..520e89c1 100644 --- a/src/core/applets/software_keyboard.cpp +++ b/src/core/applets/software_keyboard.cpp @@ -33,17 +33,22 @@ Result::HorizonResult SoftwareKeyboardApplet::receiveParameter(const Applets::Pa return Result::Success; } -Result::HorizonResult SoftwareKeyboardApplet::start(const MemoryBlock& sharedMem, const std::vector& parameters, u32 appID) { +Result::HorizonResult SoftwareKeyboardApplet::start(const MemoryBlock* sharedMem, const std::vector& parameters, u32 appID) { if (parameters.size() < sizeof(SoftwareKeyboardConfig)) { Helpers::warn("SoftwareKeyboard::Start: Invalid size for keyboard configuration"); return Result::Success; } + if (sharedMem == nullptr) { + Helpers::warn("SoftwareKeyboard: Missing shared memory"); + return Result::Success; + } + // Get keyboard configuration from the application std::memcpy(&config, ¶meters[0], sizeof(config)); const std::u16string text = u"Pand"; - u32 textAddress = sharedMem.addr; + u32 textAddress = sharedMem->addr; // Copy text to shared memory the app gave us for (u32 i = 0; i < text.size(); i++) { diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index b475b89d..404a0e59 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -155,12 +155,8 @@ void APTService::startLibraryApplet(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); } else { KernelObject* sharedMemObject = kernel.getObject(parameters); - if (sharedMemObject == nullptr) { - Helpers::warn("Couldn't find shared memory block\n"); - return; - } - const MemoryBlock* sharedMem = sharedMemObject->getData(); + const MemoryBlock* sharedMem = sharedMemObject ? sharedMemObject->getData() : nullptr; std::vector data; data.reserve(bufferSize); @@ -168,7 +164,7 @@ void APTService::startLibraryApplet(u32 messagePointer) { data.push_back(mem.read8(buffer + i)); } - Result::HorizonResult result = destApplet->start(*sharedMem, data, appID); + Result::HorizonResult result = destApplet->start(sharedMem, data, appID); if (resumeEvent.has_value()) { kernel.signalEvent(resumeEvent.value()); } diff --git a/src/core/services/ptm.cpp b/src/core/services/ptm.cpp index 4cd7e095..67451cc2 100644 --- a/src/core/services/ptm.cpp +++ b/src/core/services/ptm.cpp @@ -76,7 +76,7 @@ void PTMService::getBatteryChargeState(u32 messagePointer) { void PTMService::getPedometerState(u32 messagePointer) { log("PTM::GetPedometerState"); - const bool countingSteps = true; + constexpr bool countingSteps = true; mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0)); mem.write32(messagePointer + 4, Result::Success);