Add Mii Selector

This commit is contained in:
wheremyfoodat 2024-01-25 03:39:48 +02:00
parent 8fc61769ab
commit 6e6c84eebb
7 changed files with 150 additions and 13 deletions

View file

@ -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<u8>& parameters, u32 appID) = 0;
virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector<u8>& parameters, u32 appID) = 0;
// Transfer parameters from application -> applet
virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0;
virtual void reset() = 0;

View file

@ -1,13 +1,83 @@
#include <string>
#include "applets/applet.hpp"
#include "swap.hpp"
namespace Applets {
struct MiiConfig {
u8 enableCancelButton;
u8 enableGuestMii;
u8 showOnTopScreen;
std::array<u8, 0x5> pad1;
std::array<u16_le, 0x40> title;
std::array<u8, 0x4> pad2;
u8 showGuestMiis;
std::array<u8, 0x3> pad3;
u32 initiallySelectedIndex;
std::array<u8, 0x6> guestMiiWhitelist;
std::array<u8, 0x64> userMiiWhitelist;
std::array<u8, 0x2> 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<u8, 0x6> creatorMAC;
u16 padding;
u16_be miiDetails;
std::array<char16_t, 0xA> 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<char16_t, 0xA> 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<u16_le, 0xC> 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<u8>& parameters, u32 appID) override;
virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector<u8>& 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<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
};
} // namespace Applets

View file

@ -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<u8>& parameters, u32 appID) override;
virtual Result::HorizonResult start(const MemoryBlock* sharedMem, const std::vector<u8>& parameters, u32 appID) override;
virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override;
virtual void reset() override;

View file

@ -1,11 +1,38 @@
#include "applets/mii_selector.hpp"
#include <boost/crc.hpp>
#include <limits>
#include "kernel/handles.hpp"
using namespace Applets;
void MiiSelectorApplet::reset() {}
Result::HorizonResult MiiSelectorApplet::start(const MemoryBlock& sharedMem, const std::vector<u8>& parameters, u32 appID) { return Result::Success; }
Result::HorizonResult MiiSelectorApplet::start(const MemoryBlock* sharedMem, const std::vector<u8>& parameters, u32 appID) {
// Get mii configuration from the application
std::memcpy(&config, &parameters[0], sizeof(config));
Applets::Parameter param = Applets::Parameter{
.senderID = appID,
.destID = AppletIDs::Application,
.signal = static_cast<u32>(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<u32>::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(&param.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<u32>::max();
result.selectedMiiData = miiData;
result.guestMiiName.fill(0x0);
return result;
}

View file

@ -33,17 +33,22 @@ Result::HorizonResult SoftwareKeyboardApplet::receiveParameter(const Applets::Pa
return Result::Success;
}
Result::HorizonResult SoftwareKeyboardApplet::start(const MemoryBlock& sharedMem, const std::vector<u8>& parameters, u32 appID) {
Result::HorizonResult SoftwareKeyboardApplet::start(const MemoryBlock* sharedMem, const std::vector<u8>& 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, &parameters[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++) {

View file

@ -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<MemoryBlock>();
const MemoryBlock* sharedMem = sharedMemObject ? sharedMemObject->getData<MemoryBlock>() : nullptr;
std::vector<u8> 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());
}

View file

@ -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);