nfp: Validate amiibo files
This commit is contained in:
parent
41b65d38fa
commit
29f9a454eb
|
@ -108,7 +108,7 @@ void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
const auto result = nfp_interface.StartDetection();
|
const auto result = nfp_interface.StartDetection(nfp_protocol);
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
return;
|
return;
|
||||||
|
@ -209,7 +209,6 @@ void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) {
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
std::vector<u8> data{};
|
std::vector<u8> data{};
|
||||||
const auto result = nfp_interface.GetApplicationArea(data);
|
const auto result = nfp_interface.GetApplicationArea(data);
|
||||||
|
|
||||||
ctx.WriteBuffer(data);
|
ctx.WriteBuffer(data);
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
|
@ -232,7 +231,6 @@ void IUser::SetApplicationArea(Kernel::HLERequestContext& ctx) {
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
const auto result = nfp_interface.SetApplicationArea(data);
|
const auto result = nfp_interface.SetApplicationArea(data);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
return;
|
return;
|
||||||
|
@ -255,7 +253,6 @@ void IUser::CreateApplicationArea(Kernel::HLERequestContext& ctx) {
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
const auto result = nfp_interface.CreateApplicationArea(access_id, data);
|
const auto result = nfp_interface.CreateApplicationArea(access_id, data);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
return;
|
return;
|
||||||
|
@ -390,7 +387,7 @@ void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUser::GetState(Kernel::HLERequestContext& ctx) {
|
void IUser::GetState(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_DEBUG(Service_NFC, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3, 0};
|
IPC::ResponseBuilder rb{ctx, 3, 0};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -400,7 +397,7 @@ void IUser::GetState(Kernel::HLERequestContext& ctx) {
|
||||||
void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
|
void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
|
LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
|
||||||
|
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
|
@ -419,7 +416,7 @@ void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
|
||||||
void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
|
void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
|
LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
|
||||||
|
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
|
@ -438,7 +435,7 @@ void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
|
||||||
void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) {
|
void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
|
LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
|
||||||
|
|
||||||
// TODO(german77): Loop through all interfaces
|
// TODO(german77): Loop through all interfaces
|
||||||
if (device_handle == nfp_interface.GetHandle()) {
|
if (device_handle == nfp_interface.GetHandle()) {
|
||||||
|
@ -493,6 +490,11 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFP, "New Amiibo detected");
|
LOG_INFO(Service_NFP, "New Amiibo detected");
|
||||||
std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
|
std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
|
||||||
|
|
||||||
|
if (!IsAmiiboValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
device_state = DeviceState::TagFound;
|
device_state = DeviceState::TagFound;
|
||||||
activate_event->GetWritableEvent().Signal();
|
activate_event->GetWritableEvent().Signal();
|
||||||
return true;
|
return true;
|
||||||
|
@ -501,13 +503,54 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
|
||||||
void Module::Interface::CloseAmiibo() {
|
void Module::Interface::CloseAmiibo() {
|
||||||
LOG_INFO(Service_NFP, "Remove amiibo");
|
LOG_INFO(Service_NFP, "Remove amiibo");
|
||||||
device_state = DeviceState::TagRemoved;
|
device_state = DeviceState::TagRemoved;
|
||||||
write_counter = 0;
|
|
||||||
is_application_area_initialized = false;
|
is_application_area_initialized = false;
|
||||||
application_area_id = 0;
|
application_area_id = 0;
|
||||||
application_area_data.clear();
|
application_area_data.clear();
|
||||||
deactivate_event->GetWritableEvent().Signal();
|
deactivate_event->GetWritableEvent().Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Module::Interface::IsAmiiboValid() const {
|
||||||
|
LOG_INFO(Service_NFP, "uuid_lock=0x{0:x}", amiibo.uuid_lock);
|
||||||
|
LOG_INFO(Service_NFP, "compability_container=0x{0:x}", amiibo.compability_container);
|
||||||
|
LOG_INFO(Service_NFP, "crypto_init=0x{0:x}", amiibo.crypto_init);
|
||||||
|
LOG_INFO(Service_NFP, "write_count={}", amiibo.write_count);
|
||||||
|
|
||||||
|
LOG_INFO(Service_NFP, "character_id=0x{0:x}", amiibo.model_info.character_id);
|
||||||
|
LOG_INFO(Service_NFP, "character_variant={}", amiibo.model_info.character_variant);
|
||||||
|
LOG_INFO(Service_NFP, "amiibo_type={}", amiibo.model_info.amiibo_type);
|
||||||
|
LOG_INFO(Service_NFP, "model_number=0x{0:x}", amiibo.model_info.model_number);
|
||||||
|
LOG_INFO(Service_NFP, "series={}", amiibo.model_info.series);
|
||||||
|
LOG_INFO(Service_NFP, "fixed_value=0x{0:x}", amiibo.model_info.fixed);
|
||||||
|
|
||||||
|
LOG_INFO(Service_NFP, "tag_dynamic_lock=0x{0:x}", amiibo.tag_dynamic_lock);
|
||||||
|
LOG_INFO(Service_NFP, "tag_CFG0=0x{0:x}", amiibo.tag_CFG0);
|
||||||
|
LOG_INFO(Service_NFP, "tag_CFG1=0x{0:x}", amiibo.tag_CFG1);
|
||||||
|
|
||||||
|
// Check against all know constants on an amiibo binary
|
||||||
|
if (amiibo.uuid_lock != 0xE00F) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amiibo.compability_container != 0xEEFF10F1UL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((amiibo.crypto_init & 0xFF) != 0xA5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amiibo.model_info.fixed != 0x02) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((amiibo.tag_dynamic_lock & 0xFFFFFF) != 0x0F0001) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amiibo.tag_CFG0 != 0x04000000UL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amiibo.tag_CFG1 != 0x5F) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Kernel::KReadableEvent& Module::Interface::GetActivateEvent() const {
|
Kernel::KReadableEvent& Module::Interface::GetActivateEvent() const {
|
||||||
return activate_event->GetReadableEvent();
|
return activate_event->GetReadableEvent();
|
||||||
}
|
}
|
||||||
|
@ -522,13 +565,12 @@ void Module::Interface::Initialize() {
|
||||||
|
|
||||||
void Module::Interface::Finalize() {
|
void Module::Interface::Finalize() {
|
||||||
device_state = DeviceState::Unaviable;
|
device_state = DeviceState::Unaviable;
|
||||||
write_counter = 0;
|
|
||||||
is_application_area_initialized = false;
|
is_application_area_initialized = false;
|
||||||
application_area_id = 0;
|
application_area_id = 0;
|
||||||
application_area_data.clear();
|
application_area_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode Module::Interface::StartDetection() {
|
ResultCode Module::Interface::StartDetection(s32 protocol_) {
|
||||||
auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
|
auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
|
||||||
|
|
||||||
// TODO(german77): Add callback for when nfc data is available
|
// TODO(german77): Add callback for when nfc data is available
|
||||||
|
@ -536,6 +578,7 @@ ResultCode Module::Interface::StartDetection() {
|
||||||
if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
|
if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
|
||||||
npad_device->SetPollingMode(Common::Input::PollingMode::NFC);
|
npad_device->SetPollingMode(Common::Input::PollingMode::NFC);
|
||||||
device_state = DeviceState::SearchingForTag;
|
device_state = DeviceState::SearchingForTag;
|
||||||
|
protocol = protocol_;
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,8 +632,8 @@ ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const {
|
||||||
tag_info = {
|
tag_info = {
|
||||||
.uuid = amiibo.uuid,
|
.uuid = amiibo.uuid,
|
||||||
.uuid_length = static_cast<u8>(amiibo.uuid.size()),
|
.uuid_length = static_cast<u8>(amiibo.uuid.size()),
|
||||||
.protocol = 0xFFFFFFFF, // TODO(ogniK): Figure out actual values
|
.protocol = protocol,
|
||||||
.tag_type = 0xFFFFFFFF,
|
.tag_type = static_cast<u32>(amiibo.model_info.amiibo_type),
|
||||||
};
|
};
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -610,7 +653,7 @@ ResultCode Module::Interface::GetCommonInfo(CommonInfo& common_info) const {
|
||||||
.last_write_year = 2022,
|
.last_write_year = 2022,
|
||||||
.last_write_month = 2,
|
.last_write_month = 2,
|
||||||
.last_write_day = 7,
|
.last_write_day = 7,
|
||||||
.write_counter = write_counter,
|
.write_counter = amiibo.write_count,
|
||||||
.version = 1,
|
.version = 1,
|
||||||
.application_area_size = ApplicationAreaSize,
|
.application_area_size = ApplicationAreaSize,
|
||||||
};
|
};
|
||||||
|
@ -652,11 +695,11 @@ ResultCode Module::Interface::OpenApplicationArea(u32 access_id) {
|
||||||
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
||||||
return ErrCodes::WrongDeviceState;
|
return ErrCodes::WrongDeviceState;
|
||||||
}
|
}
|
||||||
// if (AmiiboApplicationDataExist(access_id)) {
|
if (AmiiboApplicationDataExist(access_id)) {
|
||||||
// application_area_data = LoadAmiiboApplicationData(access_id);
|
application_area_data = LoadAmiiboApplicationData(access_id);
|
||||||
// application_area_id = access_id;
|
application_area_id = access_id;
|
||||||
// is_application_area_initialized = true;
|
is_application_area_initialized = true;
|
||||||
// }
|
}
|
||||||
if (!is_application_area_initialized) {
|
if (!is_application_area_initialized) {
|
||||||
LOG_ERROR(Service_NFP, "Application area is not initialized");
|
LOG_ERROR(Service_NFP, "Application area is not initialized");
|
||||||
return ErrCodes::ApplicationAreaIsNotInitialized;
|
return ErrCodes::ApplicationAreaIsNotInitialized;
|
||||||
|
@ -689,8 +732,7 @@ ResultCode Module::Interface::SetApplicationArea(const std::vector<u8>& data) {
|
||||||
return ErrCodes::ApplicationAreaIsNotInitialized;
|
return ErrCodes::ApplicationAreaIsNotInitialized;
|
||||||
}
|
}
|
||||||
application_area_data = data;
|
application_area_data = data;
|
||||||
write_counter++;
|
SaveAmiiboApplicationData(application_area_id, application_area_data);
|
||||||
// SaveAmiiboApplicationData(application_area_id,application_area_data);
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,21 +741,32 @@ ResultCode Module::Interface::CreateApplicationArea(u32 access_id, const std::ve
|
||||||
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
||||||
return ErrCodes::WrongDeviceState;
|
return ErrCodes::WrongDeviceState;
|
||||||
}
|
}
|
||||||
// if (AmiiboApplicationDataExist(access_id)) {
|
if (AmiiboApplicationDataExist(access_id)) {
|
||||||
// LOG_ERROR(Service_NFP, "Application area already exist");
|
LOG_ERROR(Service_NFP, "Application area already exist");
|
||||||
// return ErrCodes::ApplicationAreaExist;
|
return ErrCodes::ApplicationAreaExist;
|
||||||
// }
|
}
|
||||||
// if (LoadAmiiboApplicationData(access_id,data)) {
|
|
||||||
// is_application_area_initialized = true;
|
|
||||||
// application_area_id = access_id;
|
|
||||||
// }
|
|
||||||
application_area_data = data;
|
application_area_data = data;
|
||||||
application_area_id = access_id;
|
application_area_id = access_id;
|
||||||
write_counter = 0;
|
SaveAmiiboApplicationData(application_area_id, application_area_data);
|
||||||
// SaveAmiiboApplicationData(application_area_id,application_area_data);
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Module::Interface::AmiiboApplicationDataExist(u32 access_id) const {
|
||||||
|
// TODO(german77): Check if file exist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<u8> Module::Interface::LoadAmiiboApplicationData(u32 access_id) const {
|
||||||
|
// TODO(german77): Read file
|
||||||
|
std::vector<u8> data(ApplicationAreaSize);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::SaveAmiiboApplicationData(u32 access_id,
|
||||||
|
const std::vector<u8>& data) const {
|
||||||
|
// TODO(german77): Save file
|
||||||
|
}
|
||||||
|
|
||||||
u64 Module::Interface::GetHandle() const {
|
u64 Module::Interface::GetHandle() const {
|
||||||
// Generate a handle based of the npad id
|
// Generate a handle based of the npad id
|
||||||
return static_cast<u64>(npad_id);
|
return static_cast<u64>(npad_id);
|
||||||
|
|
|
@ -53,11 +53,43 @@ enum class MountTarget : u32 {
|
||||||
All,
|
All,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class AmiiboType : u8 {
|
||||||
|
Figure,
|
||||||
|
Card,
|
||||||
|
Yarn,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AmiiboSeries : u8 {
|
||||||
|
SuperSmashBros,
|
||||||
|
SuperMario,
|
||||||
|
ChibiRobo,
|
||||||
|
YoshiWoollyWorld,
|
||||||
|
Splatoon,
|
||||||
|
AnimalCrossing,
|
||||||
|
EightBitMario,
|
||||||
|
Skylanders,
|
||||||
|
Unknown8,
|
||||||
|
TheLegendOfZelda,
|
||||||
|
ShovelKnight,
|
||||||
|
Unknown11,
|
||||||
|
Kiby,
|
||||||
|
Pokemon,
|
||||||
|
MarioSportsSuperstars,
|
||||||
|
MonsterHunter,
|
||||||
|
BoxBoy,
|
||||||
|
Pikmin,
|
||||||
|
FireEmblem,
|
||||||
|
Metroid,
|
||||||
|
Others,
|
||||||
|
MegaMan,
|
||||||
|
Diablo
|
||||||
|
};
|
||||||
|
|
||||||
struct TagInfo {
|
struct TagInfo {
|
||||||
std::array<u8, 10> uuid;
|
std::array<u8, 10> uuid;
|
||||||
u8 uuid_length;
|
u8 uuid_length;
|
||||||
INSERT_PADDING_BYTES(0x15);
|
INSERT_PADDING_BYTES(0x15);
|
||||||
u32 protocol;
|
s32 protocol;
|
||||||
u32 tag_type;
|
u32 tag_type;
|
||||||
INSERT_PADDING_BYTES(0x30);
|
INSERT_PADDING_BYTES(0x30);
|
||||||
};
|
};
|
||||||
|
@ -77,10 +109,13 @@ static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
|
||||||
struct ModelInfo {
|
struct ModelInfo {
|
||||||
u16 character_id;
|
u16 character_id;
|
||||||
u8 character_variant;
|
u8 character_variant;
|
||||||
u8 figure_type;
|
AmiiboType amiibo_type;
|
||||||
u16 model_number;
|
u16 model_number;
|
||||||
u8 series;
|
AmiiboSeries series;
|
||||||
INSERT_PADDING_BYTES(0x39);
|
u8 fixed; // Must be 02
|
||||||
|
INSERT_PADDING_BYTES(0x4); // Unknown
|
||||||
|
INSERT_PADDING_BYTES(0x20); // Probably a SHA256-(HMAC?) hash
|
||||||
|
INSERT_PADDING_BYTES(0x14); // SHA256-HMAC
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
|
static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
|
||||||
|
|
||||||
|
@ -105,11 +140,21 @@ public:
|
||||||
|
|
||||||
struct AmiiboFile {
|
struct AmiiboFile {
|
||||||
std::array<u8, 10> uuid;
|
std::array<u8, 10> uuid;
|
||||||
INSERT_PADDING_BYTES(0x4); // Compability container
|
u16 uuid_lock; // Must be 0F E0
|
||||||
INSERT_PADDING_BYTES(0x46);
|
u32 compability_container; // Must be F1 10 FF EE
|
||||||
ModelInfo model_info;
|
u16 crypto_init; // Must be A5 XX
|
||||||
|
u16 write_count; // Number of times the amiibo has been written?
|
||||||
|
INSERT_PADDING_BYTES(0x20); // System crypts
|
||||||
|
INSERT_PADDING_BYTES(0x20); // SHA256-(HMAC?) hash
|
||||||
|
ModelInfo model_info; // This struct is bigger than documentation
|
||||||
|
INSERT_PADDING_BYTES(0xC); // SHA256-HMAC
|
||||||
|
INSERT_PADDING_BYTES(0x114); // section 1 encrypted buffer
|
||||||
|
INSERT_PADDING_BYTES(0x54); // section 2 encrypted buffer
|
||||||
|
u32 tag_dynamic_lock; // Must be 01 00 0F XX
|
||||||
|
u32 tag_CFG0; // Must be 00 00 00 04
|
||||||
|
u32 tag_CFG1; // Must be 50 00 00 00
|
||||||
};
|
};
|
||||||
static_assert(sizeof(AmiiboFile) == 0x94, "AmiiboFile is an invalid size");
|
static_assert(sizeof(AmiiboFile) == 0x214, "AmiiboFile is an invalid size");
|
||||||
|
|
||||||
void CreateUserInterface(Kernel::HLERequestContext& ctx);
|
void CreateUserInterface(Kernel::HLERequestContext& ctx);
|
||||||
bool LoadAmiibo(const std::vector<u8>& buffer);
|
bool LoadAmiibo(const std::vector<u8>& buffer);
|
||||||
|
@ -118,7 +163,7 @@ public:
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
ResultCode StartDetection();
|
ResultCode StartDetection(s32 protocol_);
|
||||||
ResultCode StopDetection();
|
ResultCode StopDetection();
|
||||||
ResultCode Mount();
|
ResultCode Mount();
|
||||||
ResultCode Unmount();
|
ResultCode Unmount();
|
||||||
|
@ -144,6 +189,12 @@ public:
|
||||||
std::shared_ptr<Module> module;
|
std::shared_ptr<Module> module;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Validates that the amiibo file is not corrupted
|
||||||
|
bool IsAmiiboValid() const;
|
||||||
|
bool AmiiboApplicationDataExist(u32 access_id) const;
|
||||||
|
const std::vector<u8> LoadAmiiboApplicationData(u32 access_id) const;
|
||||||
|
void SaveAmiiboApplicationData(u32 access_id, const std::vector<u8>& data) const;
|
||||||
|
|
||||||
const Core::HID::NpadIdType npad_id;
|
const Core::HID::NpadIdType npad_id;
|
||||||
|
|
||||||
DeviceState device_state{DeviceState::Unaviable};
|
DeviceState device_state{DeviceState::Unaviable};
|
||||||
|
@ -151,7 +202,7 @@ public:
|
||||||
Kernel::KEvent* activate_event;
|
Kernel::KEvent* activate_event;
|
||||||
Kernel::KEvent* deactivate_event;
|
Kernel::KEvent* deactivate_event;
|
||||||
AmiiboFile amiibo{};
|
AmiiboFile amiibo{};
|
||||||
u16 write_counter{};
|
s32 protocol;
|
||||||
bool is_application_area_initialized{};
|
bool is_application_area_initialized{};
|
||||||
u32 application_area_id;
|
u32 application_area_id;
|
||||||
std::vector<u8> application_area_data;
|
std::vector<u8> application_area_data;
|
||||||
|
|
Reference in New Issue