mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 06:35:40 +12:00
Add Mii Selector
This commit is contained in:
parent
8fc61769ab
commit
6e6c84eebb
7 changed files with 150 additions and 13 deletions
|
@ -84,7 +84,7 @@ namespace Applets {
|
||||||
virtual const char* name() = 0;
|
virtual const char* name() = 0;
|
||||||
|
|
||||||
// Called by APT::StartLibraryApplet and similar
|
// 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
|
// Transfer parameters from application -> applet
|
||||||
virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0;
|
virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0;
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
|
@ -1,13 +1,83 @@
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "applets/applet.hpp"
|
#include "applets/applet.hpp"
|
||||||
|
#include "swap.hpp"
|
||||||
|
|
||||||
namespace Applets {
|
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 {
|
class MiiSelectorApplet final : public AppletBase {
|
||||||
public:
|
public:
|
||||||
virtual const char* name() override { return "Mii Selector"; }
|
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 Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
|
MiiResult output;
|
||||||
|
MiiConfig config;
|
||||||
|
MiiResult getDefaultMii();
|
||||||
MiiSelectorApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
|
MiiSelectorApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
|
||||||
};
|
};
|
||||||
} // namespace Applets
|
} // namespace Applets
|
|
@ -150,7 +150,7 @@ namespace Applets {
|
||||||
static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software keyboard config size is wrong");
|
static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software keyboard config size is wrong");
|
||||||
|
|
||||||
virtual const char* name() override { return "Software Keyboard"; }
|
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 Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,38 @@
|
||||||
#include "applets/mii_selector.hpp"
|
#include "applets/mii_selector.hpp"
|
||||||
|
|
||||||
|
#include <boost/crc.hpp>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "kernel/handles.hpp"
|
#include "kernel/handles.hpp"
|
||||||
|
|
||||||
using namespace Applets;
|
using namespace Applets;
|
||||||
|
|
||||||
void MiiSelectorApplet::reset() {}
|
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, ¶meters[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(¶m.data[0], &output, sizeof(output));
|
||||||
|
|
||||||
|
nextParameter = param;
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Parameter& parameter) {
|
Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Parameter& parameter) {
|
||||||
Helpers::warn("Mii Selector: Unimplemented ReceiveParameter");
|
Helpers::warn("Mii Selector: Unimplemented ReceiveParameter");
|
||||||
|
@ -20,4 +47,43 @@ Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Paramet
|
||||||
|
|
||||||
nextParameter = param;
|
nextParameter = param;
|
||||||
return Result::Success;
|
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;
|
||||||
}
|
}
|
|
@ -33,17 +33,22 @@ Result::HorizonResult SoftwareKeyboardApplet::receiveParameter(const Applets::Pa
|
||||||
return Result::Success;
|
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)) {
|
if (parameters.size() < sizeof(SoftwareKeyboardConfig)) {
|
||||||
Helpers::warn("SoftwareKeyboard::Start: Invalid size for keyboard configuration");
|
Helpers::warn("SoftwareKeyboard::Start: Invalid size for keyboard configuration");
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sharedMem == nullptr) {
|
||||||
|
Helpers::warn("SoftwareKeyboard: Missing shared memory");
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
// Get keyboard configuration from the application
|
// Get keyboard configuration from the application
|
||||||
std::memcpy(&config, ¶meters[0], sizeof(config));
|
std::memcpy(&config, ¶meters[0], sizeof(config));
|
||||||
|
|
||||||
const std::u16string text = u"Pand";
|
const std::u16string text = u"Pand";
|
||||||
u32 textAddress = sharedMem.addr;
|
u32 textAddress = sharedMem->addr;
|
||||||
|
|
||||||
// Copy text to shared memory the app gave us
|
// Copy text to shared memory the app gave us
|
||||||
for (u32 i = 0; i < text.size(); i++) {
|
for (u32 i = 0; i < text.size(); i++) {
|
||||||
|
|
|
@ -155,12 +155,8 @@ void APTService::startLibraryApplet(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
} else {
|
} else {
|
||||||
KernelObject* sharedMemObject = kernel.getObject(parameters);
|
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;
|
std::vector<u8> data;
|
||||||
data.reserve(bufferSize);
|
data.reserve(bufferSize);
|
||||||
|
|
||||||
|
@ -168,7 +164,7 @@ void APTService::startLibraryApplet(u32 messagePointer) {
|
||||||
data.push_back(mem.read8(buffer + i));
|
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()) {
|
if (resumeEvent.has_value()) {
|
||||||
kernel.signalEvent(resumeEvent.value());
|
kernel.signalEvent(resumeEvent.value());
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ void PTMService::getBatteryChargeState(u32 messagePointer) {
|
||||||
|
|
||||||
void PTMService::getPedometerState(u32 messagePointer) {
|
void PTMService::getPedometerState(u32 messagePointer) {
|
||||||
log("PTM::GetPedometerState");
|
log("PTM::GetPedometerState");
|
||||||
const bool countingSteps = true;
|
constexpr bool countingSteps = true;
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
|
Loading…
Add table
Reference in a new issue