9 changed files with 362 additions and 7 deletions
-
4src/core/CMakeLists.txt
-
20src/core/frontend/applets/cabinet.cpp
-
36src/core/frontend/applets/cabinet.h
-
169src/core/hle/service/am/applets/applet_cabinet.cpp
-
99src/core/hle/service/am/applets/applet_cabinet.h
-
20src/core/hle/service/am/applets/applets.cpp
-
12src/core/hle/service/am/applets/applets.h
-
7src/core/hle/service/nfp/nfp_types.h
-
2src/yuzu/main.cpp
@ -0,0 +1,20 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "common/logging/log.h"
|
||||
|
#include "core/frontend/applets/cabinet.h"
|
||||
|
|
||||
|
#include <thread>
|
||||
|
|
||||
|
namespace Core::Frontend { |
||||
|
|
||||
|
CabinetApplet::~CabinetApplet() = default; |
||||
|
|
||||
|
void DefaultCabinetApplet::ShowCabinetApplet( |
||||
|
std::function<void(bool, const std::string&)> callback, const CabinetParameters& parameters, |
||||
|
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const { |
||||
|
LOG_WARNING(Service_AM, "(STUBBED) called"); |
||||
|
callback(false, {}); |
||||
|
} |
||||
|
|
||||
|
} // namespace Core::Frontend
|
||||
@ -0,0 +1,36 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <functional> |
||||
|
#include "core/hle/service/nfp/nfp_types.h" |
||||
|
|
||||
|
namespace Service::NFP { |
||||
|
class NfpDevice; |
||||
|
} // namespace Service::NFP |
||||
|
|
||||
|
namespace Core::Frontend { |
||||
|
|
||||
|
struct CabinetParameters { |
||||
|
Service::NFP::TagInfo tag_info; |
||||
|
Service::NFP::RegisterInfo register_info; |
||||
|
Service::NFP::CabinetMode mode; |
||||
|
}; |
||||
|
|
||||
|
class CabinetApplet { |
||||
|
public: |
||||
|
virtual ~CabinetApplet(); |
||||
|
virtual void ShowCabinetApplet(std::function<void(bool, const std::string&)> callback, |
||||
|
const CabinetParameters& parameters, |
||||
|
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const = 0; |
||||
|
}; |
||||
|
|
||||
|
class DefaultCabinetApplet final : public CabinetApplet { |
||||
|
public: |
||||
|
void ShowCabinetApplet(std::function<void(bool, const std::string&)> callback, |
||||
|
const CabinetParameters& parameters, |
||||
|
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Core::Frontend |
||||
@ -0,0 +1,169 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "common/assert.h"
|
||||
|
#include "common/logging/log.h"
|
||||
|
#include "core/core.h"
|
||||
|
#include "core/frontend/applets/cabinet.h"
|
||||
|
#include "core/hid/hid_core.h"
|
||||
|
#include "core/hle/kernel/k_event.h"
|
||||
|
#include "core/hle/kernel/k_readable_event.h"
|
||||
|
#include "core/hle/service/am/am.h"
|
||||
|
#include "core/hle/service/am/applets/applet_cabinet.h"
|
||||
|
#include "core/hle/service/mii/mii_manager.h"
|
||||
|
#include "core/hle/service/nfp/nfp_device.h"
|
||||
|
|
||||
|
namespace Service::AM::Applets { |
||||
|
|
||||
|
Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, |
||||
|
const Core::Frontend::CabinetApplet& frontend_) |
||||
|
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{ |
||||
|
system_, |
||||
|
"CabinetApplet"} { |
||||
|
|
||||
|
availability_change_event = |
||||
|
service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); |
||||
|
} |
||||
|
|
||||
|
Cabinet::~Cabinet() = default; |
||||
|
|
||||
|
void Cabinet::Initialize() { |
||||
|
Applet::Initialize(); |
||||
|
|
||||
|
LOG_INFO(Service_HID, "Initializing Cabinet Applet."); |
||||
|
|
||||
|
LOG_ERROR(Service_HID, |
||||
|
"Initializing Applet with common_args: arg_version={}, lib_version={}, " |
||||
|
"play_startup_sound={}, size={}, system_tick={}, theme_color={}", |
||||
|
common_args.arguments_version, common_args.library_version, |
||||
|
common_args.play_startup_sound, common_args.size, common_args.system_tick, |
||||
|
common_args.theme_color); |
||||
|
|
||||
|
const auto storage = broker.PopNormalDataToApplet(); |
||||
|
ASSERT(storage != nullptr); |
||||
|
|
||||
|
const auto applet_input_data = storage->GetData(); |
||||
|
ASSERT(applet_input_data.size() >= sizeof(StartParamForAmiiboSettings)); |
||||
|
|
||||
|
std::memcpy(&applet_input_common, applet_input_data.data(), |
||||
|
sizeof(StartParamForAmiiboSettings)); |
||||
|
} |
||||
|
|
||||
|
bool Cabinet::TransactionComplete() const { |
||||
|
return is_complete; |
||||
|
} |
||||
|
|
||||
|
Result Cabinet::GetStatus() const { |
||||
|
return ResultSuccess; |
||||
|
} |
||||
|
|
||||
|
void Cabinet::ExecuteInteractive() { |
||||
|
ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet."); |
||||
|
} |
||||
|
|
||||
|
void Cabinet::Execute() { |
||||
|
if (is_complete) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const auto callback = [this](bool apply_changes, const std::string& amiibo_name) { |
||||
|
DisplayCompleted(apply_changes, amiibo_name); |
||||
|
}; |
||||
|
|
||||
|
// TODO: listen on all controllers
|
||||
|
if (nfp_device == nullptr) { |
||||
|
nfp_device = std::make_shared<Service::NFP::NfpDevice>( |
||||
|
system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event); |
||||
|
nfp_device->Initialize(); |
||||
|
nfp_device->StartDetection(Service::NFP::TagProtocol::All); |
||||
|
} |
||||
|
|
||||
|
const Core::Frontend::CabinetParameters parameters{ |
||||
|
.tag_info = applet_input_common.tag_info, |
||||
|
.register_info = applet_input_common.register_info, |
||||
|
.mode = applet_input_common.applet_mode, |
||||
|
}; |
||||
|
|
||||
|
switch (applet_input_common.applet_mode) { |
||||
|
case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: |
||||
|
case Service::NFP::CabinetMode::StartGameDataEraser: |
||||
|
case Service::NFP::CabinetMode::StartRestorer: |
||||
|
case Service::NFP::CabinetMode::StartFormatter: |
||||
|
frontend.ShowCabinetApplet(callback, parameters, nfp_device); |
||||
|
break; |
||||
|
default: |
||||
|
UNIMPLEMENTED_MSG("Unknown CabinetMode={}", applet_input_common.applet_mode); |
||||
|
DisplayCompleted(false, {}); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_name) { |
||||
|
Service::Mii::MiiManager manager; |
||||
|
ReturnValueForAmiiboSettings applet_output{}; |
||||
|
|
||||
|
if (!apply_changes) { |
||||
|
Cancel(); |
||||
|
} |
||||
|
|
||||
|
if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && |
||||
|
nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { |
||||
|
Cancel(); |
||||
|
} |
||||
|
|
||||
|
if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound) { |
||||
|
nfp_device->Mount(Service::NFP::MountTarget::All); |
||||
|
} |
||||
|
|
||||
|
switch (applet_input_common.applet_mode) { |
||||
|
case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { |
||||
|
Service::NFP::AmiiboName name{}; |
||||
|
memccpy(name.data(), amiibo_name.data(), 0, name.size()); |
||||
|
nfp_device->SetNicknameAndOwner(name); |
||||
|
break; |
||||
|
} |
||||
|
case Service::NFP::CabinetMode::StartGameDataEraser: |
||||
|
nfp_device->DeleteApplicationArea(); |
||||
|
break; |
||||
|
case Service::NFP::CabinetMode::StartRestorer: |
||||
|
nfp_device->RestoreAmiibo(); |
||||
|
break; |
||||
|
case Service::NFP::CabinetMode::StartFormatter: |
||||
|
nfp_device->DeleteAllData(); |
||||
|
break; |
||||
|
default: |
||||
|
UNIMPLEMENTED_MSG("Unknown CabinetMode={}", applet_input_common.applet_mode); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
applet_output.device_handle = applet_input_common.device_handle; |
||||
|
applet_output.result = CabinetResult::Success; |
||||
|
nfp_device->GetRegisterInfo(applet_output.register_info); |
||||
|
nfp_device->GetTagInfo(applet_output.tag_info); |
||||
|
nfp_device->Finalize(); |
||||
|
|
||||
|
std::vector<u8> out_data(sizeof(ReturnValueForAmiiboSettings)); |
||||
|
std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings)); |
||||
|
|
||||
|
is_complete = true; |
||||
|
|
||||
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); |
||||
|
broker.SignalStateChanged(); |
||||
|
} |
||||
|
|
||||
|
void Cabinet::Cancel() { |
||||
|
ReturnValueForAmiiboSettings applet_output{}; |
||||
|
applet_output.device_handle = applet_input_common.device_handle; |
||||
|
applet_output.result = CabinetResult::Cancel; |
||||
|
nfp_device->Finalize(); |
||||
|
|
||||
|
std::vector<u8> out_data(sizeof(ReturnValueForAmiiboSettings)); |
||||
|
std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings)); |
||||
|
|
||||
|
is_complete = true; |
||||
|
|
||||
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); |
||||
|
broker.SignalStateChanged(); |
||||
|
} |
||||
|
|
||||
|
} // namespace Service::AM::Applets
|
||||
@ -0,0 +1,99 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
|
||||
|
#include "core/hle/result.h" |
||||
|
#include "core/hle/service/am/applets/applets.h" |
||||
|
#include "core/hle/service/kernel_helpers.h" |
||||
|
#include "core/hle/service/nfp/nfp_types.h" |
||||
|
|
||||
|
namespace Kernel { |
||||
|
class KEvent; |
||||
|
class KReadableEvent; |
||||
|
} // namespace Kernel |
||||
|
|
||||
|
namespace Core { |
||||
|
class System; |
||||
|
} // namespace Core |
||||
|
|
||||
|
namespace Service::NFP { |
||||
|
class NfpDevice; |
||||
|
} |
||||
|
|
||||
|
namespace Service::AM::Applets { |
||||
|
|
||||
|
enum class CabinetAppletVersion : s32 { |
||||
|
Version1 = 0x1, |
||||
|
}; |
||||
|
|
||||
|
enum class CabinetResult : u8 { |
||||
|
Cancel, |
||||
|
Success, |
||||
|
}; |
||||
|
|
||||
|
// This is nn::nfp::AmiiboSettingsStartParam |
||||
|
struct AmiiboSettingsStartParam { |
||||
|
u64 device_handle; |
||||
|
std::array<u8, 0x20> param_1; |
||||
|
std::array<u8, 0x1> param_2; |
||||
|
}; |
||||
|
static_assert(sizeof(AmiiboSettingsStartParam) == 0x30, |
||||
|
"AmiiboSettingsStartParam is an invalid size"); |
||||
|
|
||||
|
// This is nn::nfp::StartParamForAmiiboSettings |
||||
|
struct StartParamForAmiiboSettings { |
||||
|
u8 param_1; |
||||
|
Service::NFP::CabinetMode applet_mode; |
||||
|
u8 flags; |
||||
|
u8 amiibo_settings_1; |
||||
|
u64 device_handle; |
||||
|
Service::NFP::TagInfo tag_info; |
||||
|
Service::NFP::RegisterInfo register_info; |
||||
|
std::array<u8, 0x20> amiibo_settings_3; |
||||
|
INSERT_PADDING_BYTES(0x20); |
||||
|
}; |
||||
|
static_assert(sizeof(StartParamForAmiiboSettings) == 0x1A8, |
||||
|
"StartParamForAmiiboSettings is an invalid size"); |
||||
|
|
||||
|
// This is nn::nfp::ReturnValueForAmiiboSettings |
||||
|
struct ReturnValueForAmiiboSettings { |
||||
|
CabinetResult result; |
||||
|
INSERT_PADDING_BYTES(0x3); |
||||
|
u64 device_handle; |
||||
|
Service::NFP::TagInfo tag_info; |
||||
|
Service::NFP::RegisterInfo register_info; |
||||
|
INSERT_PADDING_BYTES(0x24); |
||||
|
}; |
||||
|
static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x190, |
||||
|
"ReturnValueForAmiiboSettings is an invalid size"); |
||||
|
|
||||
|
class Cabinet final : public Applet { |
||||
|
public: |
||||
|
explicit Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, |
||||
|
const Core::Frontend::CabinetApplet& frontend_); |
||||
|
~Cabinet() override; |
||||
|
|
||||
|
void Initialize() override; |
||||
|
|
||||
|
bool TransactionComplete() const override; |
||||
|
Result GetStatus() const override; |
||||
|
void ExecuteInteractive() override; |
||||
|
void Execute() override; |
||||
|
void DisplayCompleted(bool apply_changes, const std::string& amiibo_name); |
||||
|
void Cancel(); |
||||
|
|
||||
|
private: |
||||
|
const Core::Frontend::CabinetApplet& frontend; |
||||
|
Core::System& system; |
||||
|
|
||||
|
bool is_complete{false}; |
||||
|
std::shared_ptr<Service::NFP::NfpDevice> nfp_device; |
||||
|
Kernel::KEvent* availability_change_event; |
||||
|
KernelHelpers::ServiceContext service_context; |
||||
|
StartParamForAmiiboSettings applet_input_common{}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Service::AM::Applets |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue