diff options
Diffstat (limited to 'src/core/hle/service')
46 files changed, 559 insertions, 162 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index deeca925d..a17c46121 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -945,7 +945,7 @@ public: {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, {10, &ILibraryAppletAccessor::Start, "Start"}, - {20, nullptr, "RequestExit"}, + {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, {25, nullptr, "Terminate"}, {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, @@ -1010,6 +1010,15 @@ private: rb.Push(ResultSuccess); } + void RequestExit(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + ASSERT(applet != nullptr); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(applet->RequestExit()); + } + void PushInData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); @@ -1265,7 +1274,8 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) } std::vector<u8> memory(transfer_mem->GetSize()); - system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); + system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), + memory.size()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -1298,7 +1308,8 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { } std::vector<u8> memory(transfer_mem->GetSize()); - system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); + system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), + memory.size()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 162687b29..93c9f2a55 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -174,4 +174,9 @@ void Cabinet::Cancel() { broker.SignalStateChanged(); } +Result Cabinet::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h index 84197a807..edd295a27 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/applets/applet_cabinet.h @@ -89,6 +89,7 @@ public: void Execute() override; void DisplayCompleted(bool apply_changes, std::string_view amiibo_name); void Cancel(); + Result RequestExit() override; private: const Core::Frontend::CabinetApplet& frontend; diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 58484519b..9840d2547 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -224,7 +224,8 @@ void Controller::Execute() { parameters.allow_dual_joycons, parameters.allow_left_joycon, parameters.allow_right_joycon); - frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); + frontend.ReconfigureControllers( + [this](bool is_success) { ConfigurationComplete(is_success); }, parameters); break; } case ControllerSupportMode::ShowControllerStrapGuide: @@ -232,16 +233,16 @@ void Controller::Execute() { case ControllerSupportMode::ShowControllerKeyRemappingForSystem: UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented", controller_private_arg.mode); - ConfigurationComplete(); + ConfigurationComplete(true); break; default: { - ConfigurationComplete(); + ConfigurationComplete(true); break; } } } -void Controller::ConfigurationComplete() { +void Controller::ConfigurationComplete(bool is_success) { ControllerSupportResultInfo result_info{}; // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. @@ -250,7 +251,8 @@ void Controller::ConfigurationComplete() { result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId()); - result_info.result = 0; + result_info.result = + is_success ? ControllerSupportResult::Success : ControllerSupportResult::Cancel; LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}", result_info.player_count, result_info.selected_id, result_info.result); @@ -262,4 +264,9 @@ void Controller::ConfigurationComplete() { broker.SignalStateChanged(); } +Result Controller::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h index 1f9adec65..f6c64f633 100644 --- a/src/core/hle/service/am/applets/applet_controller.h +++ b/src/core/hle/service/am/applets/applet_controller.h @@ -48,6 +48,11 @@ enum class ControllerSupportCaller : u8 { MaxControllerSupportCaller, }; +enum class ControllerSupportResult : u32 { + Success = 0, + Cancel = 2, +}; + struct ControllerSupportArgPrivate { u32 arg_private_size{}; u32 arg_size{}; @@ -112,7 +117,7 @@ struct ControllerSupportResultInfo { s8 player_count{}; INSERT_PADDING_BYTES(3); u32 selected_id{}; - u32 result{}; + ControllerSupportResult result{}; }; static_assert(sizeof(ControllerSupportResultInfo) == 0xC, "ControllerSupportResultInfo has incorrect size."); @@ -129,8 +134,9 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; - void ConfigurationComplete(); + void ConfigurationComplete(bool is_success); private: const Core::Frontend::ControllerApplet& frontend; diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index b013896b4..b46ea840c 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp @@ -209,4 +209,9 @@ void Error::DisplayCompleted() { broker.SignalStateChanged(); } +Result Error::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_error.h b/src/core/hle/service/am/applets/applet_error.h index d78d6f1d1..d822a32bb 100644 --- a/src/core/hle/service/am/applets/applet_error.h +++ b/src/core/hle/service/am/applets/applet_error.h @@ -34,6 +34,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void DisplayCompleted(); diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index 1eefa85e3..8b352020e 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp @@ -150,6 +150,11 @@ void Auth::AuthFinished(bool is_successful) { broker.SignalStateChanged(); } +Result Auth::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, const Core::Frontend::PhotoViewerApplet& frontend_) : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} @@ -202,6 +207,11 @@ void PhotoViewer::ViewFinished() { broker.SignalStateChanged(); } +Result PhotoViewer::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) : Applet{system_, applet_mode_}, id{id_}, system{system_} {} @@ -250,4 +260,9 @@ void StubApplet::Execute() { broker.SignalStateChanged(); } +Result StubApplet::RequestExit() { + // Nothing to do. + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_general_backend.h b/src/core/hle/service/am/applets/applet_general_backend.h index a9f2535a2..34ecaebb9 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.h +++ b/src/core/hle/service/am/applets/applet_general_backend.h @@ -28,6 +28,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void AuthFinished(bool is_successful = true); @@ -59,6 +60,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void ViewFinished(); @@ -80,6 +82,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; private: AppletId id; diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp index ae80ef506..d1f652c09 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp @@ -135,4 +135,9 @@ void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result, broker.SignalStateChanged(); } +Result MiiEdit::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h index d18dd3cf5..3f46fae1b 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.h +++ b/src/core/hle/service/am/applets/applet_mii_edit.h @@ -25,6 +25,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void MiiEditOutput(MiiEditResult result, s32 index); diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp index 1d69f5447..89cb323e9 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.cpp +++ b/src/core/hle/service/am/applets/applet_profile_select.cpp @@ -25,13 +25,29 @@ void ProfileSelect::Initialize() { final_data.clear(); Applet::Initialize(); + profile_select_version = ProfileSelectAppletVersion{common_args.library_version}; const auto user_config_storage = broker.PopNormalDataToApplet(); ASSERT(user_config_storage != nullptr); const auto& user_config = user_config_storage->GetData(); - ASSERT(user_config.size() >= sizeof(UserSelectionConfig)); - std::memcpy(&config, user_config.data(), sizeof(UserSelectionConfig)); + LOG_INFO(Service_AM, "Initializing Profile Select Applet with version={}", + profile_select_version); + + switch (profile_select_version) { + case ProfileSelectAppletVersion::Version1: + ASSERT(user_config.size() == sizeof(UiSettingsV1)); + std::memcpy(&config_old, user_config.data(), sizeof(UiSettingsV1)); + break; + case ProfileSelectAppletVersion::Version2: + case ProfileSelectAppletVersion::Version3: + ASSERT(user_config.size() == sizeof(UiSettings)); + std::memcpy(&config, user_config.data(), sizeof(UiSettings)); + break; + default: + UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version); + break; + } } bool ProfileSelect::TransactionComplete() const { @@ -52,11 +68,37 @@ void ProfileSelect::Execute() { return; } - frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); }); + Core::Frontend::ProfileSelectParameters parameters{}; + + switch (profile_select_version) { + case ProfileSelectAppletVersion::Version1: + parameters = { + .mode = config_old.mode, + .invalid_uid_list = config_old.invalid_uid_list, + .display_options = config_old.display_options, + .purpose = UserSelectionPurpose::General, + }; + break; + case ProfileSelectAppletVersion::Version2: + case ProfileSelectAppletVersion::Version3: + parameters = { + .mode = config.mode, + .invalid_uid_list = config.invalid_uid_list, + .display_options = config.display_options, + .purpose = config.purpose, + }; + break; + default: + UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version); + break; + } + + frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); }, + parameters); } void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { - UserSelectionOutput output{}; + UiReturnArg output{}; if (uuid.has_value() && uuid->IsValid()) { output.result = 0; @@ -67,10 +109,15 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { output.uuid_selected = Common::InvalidUUID; } - final_data = std::vector<u8>(sizeof(UserSelectionOutput)); + final_data = std::vector<u8>(sizeof(UiReturnArg)); std::memcpy(final_data.data(), &output, final_data.size()); broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); broker.SignalStateChanged(); } +Result ProfileSelect::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h index b77f1d205..369f9250f 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.h +++ b/src/core/hle/service/am/applets/applet_profile_select.h @@ -16,19 +16,100 @@ class System; namespace Service::AM::Applets { -struct UserSelectionConfig { - // TODO(DarkLordZach): RE this structure - // It seems to be flags and the like that determine the UI of the applet on the switch... from - // my research this is safe to ignore for now. - INSERT_PADDING_BYTES(0xA0); +enum class ProfileSelectAppletVersion : u32 { + Version1 = 0x1, // 1.0.0+ + Version2 = 0x10000, // 2.0.0+ + Version3 = 0x20000, // 6.0.0+ }; -static_assert(sizeof(UserSelectionConfig) == 0xA0, "UserSelectionConfig has incorrect size."); -struct UserSelectionOutput { +// This is nn::account::UiMode +enum class UiMode { + UserSelector, + UserCreator, + EnsureNetworkServiceAccountAvailable, + UserIconEditor, + UserNicknameEditor, + UserCreatorForStarter, + NintendoAccountAuthorizationRequestContext, + IntroduceExternalNetworkServiceAccount, + IntroduceExternalNetworkServiceAccountForRegistration, + NintendoAccountNnidLinker, + LicenseRequirementsForNetworkService, + LicenseRequirementsForNetworkServiceWithUserContextImpl, + UserCreatorForImmediateNaLoginTest, + UserQualificationPromoter, +}; + +// This is nn::account::UserSelectionPurpose +enum class UserSelectionPurpose { + General, + GameCardRegistration, + EShopLaunch, + EShopItemShow, + PicturePost, + NintendoAccountLinkage, + SettingsUpdate, + SaveDataDeletion, + UserMigration, + SaveDataTransfer, +}; + +// This is nn::account::NintendoAccountStartupDialogType +enum class NintendoAccountStartupDialogType { + LoginAndCreate, + Login, + Create, +}; + +// This is nn::account::UserSelectionSettingsForSystemService +struct UserSelectionSettingsForSystemService { + UserSelectionPurpose purpose; + bool enable_user_creation; + INSERT_PADDING_BYTES(0x3); +}; +static_assert(sizeof(UserSelectionSettingsForSystemService) == 0x8, + "UserSelectionSettingsForSystemService has incorrect size."); + +struct UiSettingsDisplayOptions { + bool is_network_service_account_required; + bool is_skip_enabled; + bool is_system_or_launcher; + bool is_registration_permitted; + bool show_skip_button; + bool aditional_select; + bool show_user_selector; + bool is_unqualified_user_selectable; +}; +static_assert(sizeof(UiSettingsDisplayOptions) == 0x8, + "UiSettingsDisplayOptions has incorrect size."); + +struct UiSettingsV1 { + UiMode mode; + INSERT_PADDING_BYTES(0x4); + std::array<Common::UUID, 8> invalid_uid_list; + u64 application_id; + UiSettingsDisplayOptions display_options; +}; +static_assert(sizeof(UiSettingsV1) == 0x98, "UiSettings has incorrect size."); + +// This is nn::account::UiSettings +struct UiSettings { + UiMode mode; + INSERT_PADDING_BYTES(0x4); + std::array<Common::UUID, 8> invalid_uid_list; + u64 application_id; + UiSettingsDisplayOptions display_options; + UserSelectionPurpose purpose; + INSERT_PADDING_BYTES(0x4); +}; +static_assert(sizeof(UiSettings) == 0xA0, "UiSettings has incorrect size."); + +// This is nn::account::UiReturnArg +struct UiReturnArg { u64 result; Common::UUID uuid_selected; }; -static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has incorrect size."); +static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size."); class ProfileSelect final : public Applet { public: @@ -42,13 +123,17 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void SelectionComplete(std::optional<Common::UUID> uuid); private: const Core::Frontend::ProfileSelectApplet& frontend; - UserSelectionConfig config; + UiSettings config; + UiSettingsV1 config_old; + ProfileSelectAppletVersion profile_select_version; + bool complete = false; Result status = ResultSuccess; std::vector<u8> final_data; diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp index c18236045..4145bb84f 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp @@ -770,6 +770,11 @@ void SoftwareKeyboard::ExitKeyboard() { broker.SignalStateChanged(); } +Result SoftwareKeyboard::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + // Inline Software Keyboard Requests void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) { diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h index b01b31c98..2e919811b 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.h +++ b/src/core/hle/service/am/applets/applet_software_keyboard.h @@ -31,6 +31,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; /** * Submits the input text to the application. diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index f061bae80..2accf7898 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp @@ -363,6 +363,11 @@ void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) broker.SignalStateChanged(); } +Result WebBrowser::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + bool WebBrowser::InputTLVExistsInMap(WebArgInputTLVType input_tlv_type) const { return web_arg_input_tlv_map.find(input_tlv_type) != web_arg_input_tlv_map.end(); } diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h index fd727fac8..99fe18659 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.h +++ b/src/core/hle/service/am/applets/applet_web_browser.h @@ -35,6 +35,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + Result RequestExit() override; void ExtractOfflineRomFS(); diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index a22eb62a8..12f374199 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -142,6 +142,7 @@ public: virtual Result GetStatus() const = 0; virtual void ExecuteInteractive() = 0; virtual void Execute() = 0; + virtual Result RequestExit() = 0; AppletDataBroker& GetBroker() { return broker; diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index 478d38590..bcb272eaf 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -60,10 +60,11 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti // Update seven six axis transfer memory seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); - system.Memory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); + system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, + sizeof(seven_sixaxis_lifo)); } -void Controller_ConsoleSixAxis::SetTransferMemoryAddress(VAddr t_mem) { +void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 8d3e4081b..7015d924c 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -5,8 +5,8 @@ #include <array> -#include "common/common_types.h" #include "common/quaternion.h" +#include "common/typed_address.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" @@ -34,7 +34,7 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; // Called on InitializeSevenSixAxisSensor - void SetTransferMemoryAddress(VAddr t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); // Called on ResetSevenSixAxisSensorTimestamp void ResetTimestamp(); @@ -66,7 +66,7 @@ private: static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); SevenSixAxisState next_seven_sixaxis_state{}; - VAddr transfer_memory{}; + Common::ProcessAddress transfer_memory{}; ConsoleSharedMemory* shared_memory = nullptr; Core::HID::EmulatedConsole* console = nullptr; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ba6f04d8d..8abf71608 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -70,7 +70,6 @@ Result Controller_NPad::VerifyValidSixAxisSensorHandle( const Core::HID::SixAxisSensorHandle& device_handle) { const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)); const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; - const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType; if (!npad_id) { return InvalidNpadId; @@ -78,10 +77,6 @@ Result Controller_NPad::VerifyValidSixAxisSensorHandle( if (!device_index) { return NpadDeviceIndexOutOfRange; } - // This doesn't get validated on nnsdk - if (!npad_type) { - return NpadInvalidHandle; - } return ResultSuccess; } @@ -819,12 +814,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode return communication_mode; } -Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, - NpadJoyAssignmentMode assignment_mode) { +bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_device_type, + NpadJoyAssignmentMode assignment_mode) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; + return false; } auto& controller = GetControllerFromNpadIdType(npad_id); @@ -833,7 +828,7 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, } if (!controller.device->IsConnected()) { - return ResultSuccess; + return false; } if (assignment_mode == NpadJoyAssignmentMode::Dual) { @@ -842,52 +837,52 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, controller.is_dual_left_connected = true; controller.is_dual_right_connected = false; UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return ResultSuccess; + return false; } if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { DisconnectNpad(npad_id); controller.is_dual_left_connected = false; controller.is_dual_right_connected = true; UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return ResultSuccess; + return false; } - return ResultSuccess; + return false; } // This is for NpadJoyAssignmentMode::Single // Only JoyconDual get affected by this function if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { - return ResultSuccess; + return false; } if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { DisconnectNpad(npad_id); UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - return ResultSuccess; + return false; } if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { DisconnectNpad(npad_id); UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - return ResultSuccess; + return false; } // We have two controllers connected to the same npad_id we need to split them - const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId(); - auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); + new_npad_id = hid_core.GetFirstDisconnectedNpadId(); + auto& controller_2 = GetControllerFromNpadIdType(new_npad_id); DisconnectNpad(npad_id); if (npad_device_type == NpadJoyDeviceType::Left) { UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); controller_2.is_dual_left_connected = false; controller_2.is_dual_right_connected = true; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } else { UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); controller_2.is_dual_left_connected = true; controller_2.is_dual_right_connected = false; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } - return ResultSuccess; + return true; } bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, @@ -1131,6 +1126,7 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { WriteEmptyEntry(shared_memory); return ResultSuccess; } + Result Controller_NPad::SetGyroscopeZeroDriftMode( const Core::HID::SixAxisSensorHandle& sixaxis_handle, Core::HID::GyroscopeZeroDriftMode drift_mode) { @@ -1388,7 +1384,8 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, return NpadIsDualJoycon; } - // Disconnect the joycon at the second id and connect the dual joycon at the first index. + // Disconnect the joycons and connect them as dual joycon at the first index. + DisconnectNpad(npad_id_1); DisconnectNpad(npad_id_2); controller_1.is_dual_left_connected = true; controller_1.is_dual_right_connected = true; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index a5998c453..9cfe298f1 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -102,8 +102,8 @@ public: void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); NpadCommunicationMode GetNpadCommunicationMode() const; - Result SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, - NpadJoyAssignmentMode assignment_mode); + bool SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, const Core::HID::VibrationValue& vibration_value); diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp index bce51285c..14c67e454 100644 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -152,7 +152,7 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl } Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, - VAddr t_mem, u64 size) { + Common::ProcessAddress t_mem, u64 size) { if (handle.npad_id != active_handle.npad_id) { return InvalidPalmaHandle; } diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h index cf62f0dbc..a0491a819 100644 --- a/src/core/hle/service/hid/controllers/palma.h +++ b/src/core/hle/service/hid/controllers/palma.h @@ -5,7 +5,7 @@ #include <array> #include "common/common_funcs.h" -#include "common/common_types.h" +#include "common/typed_address.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/errors.h" @@ -125,8 +125,8 @@ public: Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); - Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, VAddr t_mem, - u64 size); + Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, + Common::ProcessAddress t_mem, u64 size); Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, s32 database_id_version_); Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 4529ad643..87e7b864a 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -302,7 +302,7 @@ Hid::Hid(Core::System& system_) {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, - {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, + {133, &Hid::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"}, {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"}, {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"}, @@ -1180,8 +1180,10 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, + controller.SetNpadMode(new_npad_id, parameters.npad_id, + Controller_NPad::NpadJoyDeviceType::Left, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, @@ -1203,8 +1205,9 @@ void Hid::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, + controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", @@ -1226,8 +1229,10 @@ void Hid::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; + Core::HID::NpadIdType new_npad_id{}; auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); + controller.SetNpadMode(new_npad_id, parameters.npad_id, {}, + Controller_NPad::NpadJoyAssignmentMode::Dual); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -1369,6 +1374,34 @@ void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { rb.Push(result); } +void Hid::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Core::HID::NpadIdType npad_id; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + Controller_NPad::NpadJoyDeviceType npad_joy_device_type; + }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; + + Core::HID::NpadIdType new_npad_id{}; + auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); + const auto is_reassigned = + controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, + Controller_NPad::NpadJoyAssignmentMode::Single); + + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", + parameters.npad_id, parameters.applet_resource_user_id, + parameters.npad_joy_device_type); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(is_reassigned); + rb.PushEnum(new_npad_id); +} + void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index c69e5f3fb..f247b83c2 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -151,6 +151,7 @@ private: void SwapNpadAssignment(HLERequestContext& ctx); void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx); void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx); + void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx); void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx); void SetNpadCaptureButtonAssignment(HLERequestContext& ctx); void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx); diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp index dfd23ec04..ee522c36e 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp +++ b/src/core/hle/service/hid/hidbus/hidbus_base.cpp @@ -59,7 +59,7 @@ void HidbusBase::DisablePollingMode() { polling_mode_enabled = false; } -void HidbusBase::SetTransferMemoryAddress(VAddr t_mem) { +void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h index 26313264d..ec41684e1 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ b/src/core/hle/service/hid/hidbus/hidbus_base.h @@ -5,7 +5,7 @@ #include <array> #include <span> -#include "common/common_types.h" +#include "common/typed_address.h" #include "core/hle/result.h" namespace Core { @@ -138,7 +138,7 @@ public: void DisablePollingMode(); // Called on EnableJoyPollingReceiveMode - void SetTransferMemoryAddress(VAddr t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); Kernel::KReadableEvent& GetSendCommandAsycEvent() const; @@ -174,7 +174,7 @@ protected: JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; ButtonOnlyPollingDataAccessor button_only_data{}; - VAddr transfer_memory{}; + Common::ProcessAddress transfer_memory{}; Core::System& system; Kernel::KEvent* send_command_async_event; diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 65a2dd521..378108012 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -64,8 +64,8 @@ void RingController::OnUpdate() { curr_entry.polling_data.out_size = sizeof(ringcon_value); std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); - system.Memory().WriteBlock(transfer_memory, &enable_sixaxis_data, - sizeof(enable_sixaxis_data)); + system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data, + sizeof(enable_sixaxis_data)); break; } default: diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp index a268750cd..803a6277c 100644 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp @@ -58,16 +58,16 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType if (camera_data.format != current_config.origin_format) { LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, current_config.origin_format); - system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, - GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } if (current_config.origin_format > current_config.trimming_format) { LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", current_config.origin_format, current_config.trimming_format); - system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, - GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } @@ -84,8 +84,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", current_config.trimming_start_x, current_config.trimming_start_y, trimming_width, trimming_height, origin_width, origin_height); - system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, - GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().ZeroBlock(transfer_memory, + GetDataSize(current_config.trimming_format)); return; } @@ -99,8 +99,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType } } - system.Memory().WriteBlock(transfer_memory, window_data.data(), - GetDataSize(current_config.trimming_format)); + system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(), + GetDataSize(current_config.trimming_format)); if (!IsProcessorActive()) { StartProcessor(); @@ -140,7 +140,7 @@ void ImageTransferProcessor::SetConfig( npad_device->SetCameraFormat(current_config.origin_format); } -void ImageTransferProcessor::SetTransferMemoryAddress(VAddr t_mem) { +void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { transfer_memory = t_mem; } @@ -148,7 +148,7 @@ Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( std::vector<u8>& data) const { const auto size = GetDataSize(current_config.trimming_format); data.resize(size); - system.Memory().ReadBlock(transfer_memory, data.data(), size); + system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); return processor_state; } diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.h b/src/core/hle/service/hid/irsensor/image_transfer_processor.h index 7cfe04c8c..7f42d8453 100644 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.h +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.h @@ -3,7 +3,7 @@ #pragma once -#include "common/common_types.h" +#include "common/typed_address.h" #include "core/hid/irs_types.h" #include "core/hle/service/hid/irsensor/processor_base.h" @@ -37,7 +37,7 @@ public: void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); // Transfer memory where the image data will be stored - void SetTransferMemoryAddress(VAddr t_mem); + void SetTransferMemoryAddress(Common::ProcessAddress t_mem); Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; @@ -72,6 +72,6 @@ private: int callback_key{}; Core::System& system; - VAddr transfer_memory{}; + Common::ProcessAddress transfer_memory{}; }; } // namespace Service::IRS diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index cca697c64..2290df705 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp @@ -303,8 +303,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesti } // Copy the translated command buffer back into the thread's command buffer area. - memory.WriteBlock(owner_process, requesting_thread.GetTlsAddress(), cmd_buf.data(), - write_size * sizeof(u32)); + memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32)); return ResultSuccess; } diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 46bcfd695..be996870f 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -24,8 +24,8 @@ class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { public: explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, CodeRange user_ro) - : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, context{ - system_.Memory()} { + : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, + context{system_.ApplicationMemory()} { // clang-format off static const FunctionInfo functions[] = { {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, @@ -195,7 +195,7 @@ public: } // Set up the configuration with the required TransferMemory address - configuration.transfer_memory.offset = tmem->GetSourceAddress(); + configuration.transfer_memory.offset = GetInteger(tmem->GetSourceAddress()); configuration.transfer_memory.size = tmem_size; // Gather up all the callbacks from the loaded plugin @@ -383,12 +383,12 @@ public: } const CodeRange user_rx{ - .offset = rx_mem->GetSourceAddress(), + .offset = GetInteger(rx_mem->GetSourceAddress()), .size = parameters.rx_size, }; const CodeRange user_ro{ - .offset = ro_mem->GetSourceAddress(), + .offset = GetInteger(ro_mem->GetSourceAddress()), .size = parameters.ro_size, }; diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 6de96ed5b..c42489ff9 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -225,7 +225,7 @@ public: // Read NRR data from memory std::vector<u8> nrr_data(nrr_size); - system.Memory().ReadBlock(nrr_address, nrr_data.data(), nrr_size); + system.ApplicationMemory().ReadBlock(nrr_address, nrr_data.data(), nrr_size); NRRHeader header; std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader)); @@ -314,7 +314,7 @@ public: const auto is_region_available = [&](VAddr addr) { const auto end_addr = addr + size; while (addr < end_addr) { - if (system.Memory().IsValidVirtualAddress(addr)) { + if (system.ApplicationMemory().IsValidVirtualAddress(addr)) { return false; } @@ -337,7 +337,7 @@ public: bool succeeded = false; const auto map_region_end = - page_table.GetAliasCodeRegionStart() + page_table.GetAliasCodeRegionSize(); + GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize(); while (current_map_addr < map_region_end) { if (is_region_available(current_map_addr)) { succeeded = true; @@ -427,8 +427,8 @@ public: const VAddr bss_end_addr{ Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; - const auto CopyCode = [this, process](VAddr src_addr, VAddr dst_addr, u64 size) { - system.Memory().CopyBlock(*process, dst_addr, src_addr, size); + const auto CopyCode = [this](VAddr src_addr, VAddr dst_addr, u64 size) { + system.ApplicationMemory().CopyBlock(dst_addr, src_addr, size); }; CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, nro_header.segment_headers[TEXT_INDEX].memory_size); @@ -506,7 +506,7 @@ public: // Read NRO data from memory std::vector<u8> nro_data(nro_size); - system.Memory().ReadBlock(nro_address, nro_data.data(), nro_size); + system.ApplicationMemory().ReadBlock(nro_address, nro_data.data(), nro_size); SHA256Hash hash{}; mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0); @@ -642,7 +642,8 @@ public: LOG_WARNING(Service_LDR, "(STUBBED) called"); initialized = true; - current_map_addr = system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart(); + current_map_addr = + GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 3a2fe938f..c920650f5 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -510,7 +510,7 @@ CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { return mii; } -Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { +Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const { Service::Mii::MiiManager manager; Ver3StoreData mii_v3{}; @@ -534,16 +534,13 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.region_information.character_set.Assign(mii.font_region); mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type); - mii_v3.appearance_bits1.skin_color.Assign(mii.faceline_color); mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle); mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make); mii_v3.hair_style = mii.hair_type; - mii_v3.appearance_bits3.hair_color.Assign(mii.hair_color); mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip); mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type); - mii_v3.appearance_bits4.eye_color.Assign(mii.eye_color); mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale); mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect); mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate); @@ -551,7 +548,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y); mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type); - mii_v3.appearance_bits5.eyebrow_color.Assign(mii.eyebrow_color); mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale); mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect); mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate); @@ -563,7 +559,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y); mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type); - mii_v3.appearance_bits7.mouth_color.Assign(mii.mouth_color); mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale); mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect); mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y); @@ -573,10 +568,7 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y); mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); - mii_v3.appearance_bits9.facial_hair_color.Assign(mii.beard_color); - mii_v3.appearance_bits10.glasses_type.Assign(mii.glasses_type); - mii_v3.appearance_bits10.glasses_color.Assign(mii.glasses_color); mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); @@ -585,11 +577,36 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); + // These types are converted to V3 from a table + mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]); + mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]); + mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]); + mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]); + mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]); + mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]); + mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]); + mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]); + + mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16)); + // TODO: Validate mii_v3 data return mii_v3; } +NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { + return { + .faceline_color = static_cast<u8>(mii.faceline_color & 0xf), + .hair_color = static_cast<u8>(mii.hair_color & 0x7f), + .eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f), + .eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f), + .mouth_color = static_cast<u8>(mii.mouth_color & 0x7f), + .beard_color = static_cast<u8>(mii.beard_color & 0x7f), + .glass_color = static_cast<u8>(mii.glasses_color & 0x7f), + .glass_type = static_cast<u8>(mii.glasses_type & 0x1f), + }; +} + bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { bool is_valid = mii_v3.version == 0 || mii_v3.version == 3; diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 83ad3d343..5525fcd1c 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -23,11 +23,16 @@ public: CharInfo BuildRandom(Age age, Gender gender, Race race); CharInfo BuildDefault(std::size_t index); CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; - Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const; bool ValidateV3Info(const Ver3StoreData& mii_v3) const; ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); Result GetIndex(const CharInfo& info, u32& index); + // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData + Ver3StoreData BuildFromStoreData(const CharInfo& mii) const; + + // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData + NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; + private: const Common::UUID user_id{}; u64 update_counter{}; diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h index 9e3247397..c48d08d79 100644 --- a/src/core/hle/service/mii/types.h +++ b/src/core/hle/service/mii/types.h @@ -365,10 +365,68 @@ struct Ver3StoreData { } appearance_bits11; std::array<u16_le, 0xA> author_name; - INSERT_PADDING_BYTES(0x4); + INSERT_PADDING_BYTES(0x2); + u16_be crc; }; static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size"); +struct NfpStoreDataExtension { + u8 faceline_color; + u8 hair_color; + u8 eye_color; + u8 eyebrow_color; + u8 mouth_color; + u8 beard_color; + u8 glass_color; + u8 glass_type; +}; +static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size"); + +constexpr std::array<u8, 0x10> Ver3FacelineColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5, +}; + +constexpr std::array<u8, 100> Ver3HairColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0, + 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4, +}; + +constexpr std::array<u8, 100> Ver3EyeColorTable{ + 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4, + 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, + 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, +}; + +constexpr std::array<u8, 100> Ver3MouthlineColorTable{ + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3, +}; + +constexpr std::array<u8, 100> Ver3GlassColorTable{ + 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3, + 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, +}; + +constexpr std::array<u8, 20> Ver3GlassTypeTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, + 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7, +}; + struct MiiStoreData { using Name = std::array<char16_t, 10>; diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp index 3f17d0c7a..c7db74d14 100644 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ b/src/core/hle/service/nfc/nfc_device.cpp @@ -42,8 +42,18 @@ NfcDevice::~NfcDevice() { }; void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Connected || - type == Core::HID::ControllerTriggerType::Disconnected) { + if (!is_initalized) { + return; + } + + if (type == Core::HID::ControllerTriggerType::Connected) { + Initialize(); + availability_change_event->Signal(); + return; + } + + if (type == Core::HID::ControllerTriggerType::Disconnected) { + device_state = NFP::DeviceState::Unavailable; availability_change_event->Signal(); return; } @@ -113,6 +123,7 @@ void NfcDevice::Initialize() { device_state = npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable; encrypted_tag_data = {}; + is_initalized = true; } void NfcDevice::Finalize() { @@ -121,6 +132,7 @@ void NfcDevice::Finalize() { StopDetection(); } device_state = NFP::DeviceState::Unavailable; + is_initalized = false; } Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h index a6e114d36..ea63f0537 100644 --- a/src/core/hle/service/nfc/nfc_device.h +++ b/src/core/hle/service/nfc/nfc_device.h @@ -67,6 +67,7 @@ private: Kernel::KEvent* deactivate_event = nullptr; Kernel::KEvent* availability_change_event = nullptr; + bool is_initalized{}; NFP::TagProtocol allowed_protocols{}; NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp index ad73edbda..a3622e792 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ b/src/core/hle/service/nfp/amiibo_crypto.cpp @@ -70,6 +70,10 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { return true; } +bool IsAmiiboValid(const NTAG215File& ntag_file) { + return IsAmiiboValid(EncodedDataToNfcData(ntag_file)); +} + NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { NTAG215File encoded_data{}; @@ -88,8 +92,9 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { encoded_data.application_area_id = nfc_data.user_memory.application_area_id; encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; encoded_data.unknown = nfc_data.user_memory.unknown; + encoded_data.mii_extension = nfc_data.user_memory.mii_extension; encoded_data.unknown2 = nfc_data.user_memory.unknown2; - encoded_data.application_area_crc = nfc_data.user_memory.application_area_crc; + encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; encoded_data.application_area = nfc_data.user_memory.application_area; encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; @@ -122,8 +127,9 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { nfc_data.user_memory.application_area_id = encoded_data.application_area_id; nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; nfc_data.user_memory.unknown = encoded_data.unknown; + nfc_data.user_memory.mii_extension = encoded_data.mii_extension; nfc_data.user_memory.unknown2 = encoded_data.unknown2; - nfc_data.user_memory.application_area_crc = encoded_data.application_area_crc; + nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc; nfc_data.user_memory.application_area = encoded_data.application_area; nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag; nfc_data.user_memory.model_info = encoded_data.model_info; diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h index c9fd67a39..f6208ee6b 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.h +++ b/src/core/hle/service/nfp/amiibo_crypto.h @@ -60,6 +60,9 @@ static_assert(sizeof(DerivedKeys) == 0x30, "DerivedKeys is an invalid size"); /// Validates that the amiibo file is not corrupted bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file); +/// Validates that the amiibo file is not corrupted +bool IsAmiiboValid(const NTAG215File& ntag_file); + /// Converts from encrypted file format to encoded file format NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data); diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index ddff90d6a..607e70968 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -3,6 +3,17 @@ #include <array> +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used +#endif + +#include <boost/crc.hpp> + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #include "common/input.h" #include "common/logging/log.h" #include "common/string_util.h" @@ -55,8 +66,18 @@ NfpDevice::~NfpDevice() { }; void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Connected || - type == Core::HID::ControllerTriggerType::Disconnected) { + if (!is_initalized) { + return; + } + + if (type == Core::HID::ControllerTriggerType::Connected) { + Initialize(); + availability_change_event->Signal(); + return; + } + + if (type == Core::HID::ControllerTriggerType::Disconnected) { + device_state = DeviceState::Unavailable; availability_change_event->Signal(); return; } @@ -100,7 +121,16 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) { // TODO: Filter by allowed_protocols here - memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); + memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File)); + is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data); + + if (is_plain_amiibo) { + encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data); + LOG_INFO(Service_NFP, "Using plain amiibo"); + } else { + tag_data = {}; + memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); + } device_state = DeviceState::TagFound; deactivate_event->GetReadableEvent().Clear(); @@ -134,6 +164,7 @@ void NfpDevice::Initialize() { device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; encrypted_tag_data = {}; tag_data = {}; + is_initalized = true; } void NfpDevice::Finalize() { @@ -144,6 +175,7 @@ void NfpDevice::Finalize() { StopDetection(); } device_state = DeviceState::Unavailable; + is_initalized = false; } Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { @@ -209,13 +241,17 @@ Result NfpDevice::Flush() { tag_data.write_counter++; - if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Failed to encode data"); - return WriteAmiiboFailed; - } + std::vector<u8> data(sizeof(EncryptedNTAG215File)); + if (is_plain_amiibo) { + memcpy(data.data(), &tag_data, sizeof(tag_data)); + } else { + if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { + LOG_ERROR(Service_NFP, "Failed to encode data"); + return WriteAmiiboFailed; + } - std::vector<u8> data(sizeof(encrypted_tag_data)); - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + } if (!npad_device->WriteNfc(data)) { LOG_ERROR(Service_NFP, "Error writing to file"); @@ -233,6 +269,13 @@ Result NfpDevice::Mount(MountTarget mount_target_) { return WrongDeviceState; } + // The loaded amiibo is not encrypted + if (is_plain_amiibo) { + device_state = DeviceState::TagMounted; + mount_target = mount_target_; + return ResultSuccess; + } + if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { LOG_ERROR(Service_NFP, "Not an amiibo"); return NotAnAmiibo; @@ -448,7 +491,7 @@ Result NfpDevice::DeleteRegisterInfo() { rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8)); rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32)); rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.application_area_crc, sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32)); rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32)); tag_data.settings.settings.font_region.Assign(0); tag_data.settings.settings.amiibo_initialized.Assign(0); @@ -471,6 +514,7 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { } Service::Mii::MiiManager manager; + const auto mii = manager.BuildDefault(0); auto& settings = tag_data.settings; if (tag_data.settings.settings.amiibo_initialized == 0) { @@ -479,16 +523,15 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { } SetAmiiboName(settings, amiibo_name); - tag_data.owner_mii = manager.ConvertCharInfoToV3(manager.BuildDefault(0)); + tag_data.owner_mii = manager.BuildFromStoreData(mii); + tag_data.mii_extension = manager.SetFromStoreData(mii); tag_data.unknown = 0; - tag_data.unknown2[6] = 0; + tag_data.unknown2 = {}; settings.country_code_id = 0; settings.settings.font_region.Assign(0); settings.settings.amiibo_initialized.Assign(1); - // TODO: this is a mix of tag.file input - std::array<u8, 0x7e> unknown_input{}; - tag_data.application_area_crc = CalculateCrc(unknown_input); + UpdateRegisterInfoCrc(); return Flush(); } @@ -685,6 +728,11 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat return WrongDeviceState; } + if (is_app_area_open) { + LOG_ERROR(Service_NFP, "Application area is open"); + return WrongDeviceState; + } + if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); return WrongDeviceState; @@ -715,10 +763,9 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat tag_data.settings.settings.appdata_initialized.Assign(1); tag_data.application_area_id = access_id; tag_data.unknown = {}; + tag_data.unknown2 = {}; - // TODO: this is a mix of tag_data input - std::array<u8, 0x7e> unknown_input{}; - tag_data.application_area_crc = CalculateCrc(unknown_input); + UpdateRegisterInfoCrc(); return Flush(); } @@ -752,6 +799,10 @@ Result NfpDevice::DeleteApplicationArea() { rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); tag_data.settings.settings.appdata_initialized.Assign(0); tag_data.unknown = {}; + tag_data.unknown2 = {}; + is_app_area_open = false; + + UpdateRegisterInfoCrc(); return Flush(); } @@ -835,32 +886,34 @@ void NfpDevice::UpdateSettingsCrc() { // TODO: this reads data from a global, find what it is std::array<u8, 8> unknown_input{}; - settings.crc = CalculateCrc(unknown_input); -} - -u32 NfpDevice::CalculateCrc(std::span<const u8> data) { - constexpr u32 magic = 0xedb88320; - u32 crc = 0xffffffff; - - if (data.size() == 0) { - return 0; - } - - for (u8 input : data) { - u32 temp = (crc ^ input) >> 1; - if (((crc ^ input) & 1) != 0) { - temp = temp ^ magic; - } - - for (std::size_t step = 0; step < 7; ++step) { - crc = temp >> 1; - if ((temp & 1) != 0) { - crc = temp >> 1 ^ magic; - } - } - } + boost::crc_32_type crc; + crc.process_bytes(&unknown_input, sizeof(unknown_input)); + settings.crc = crc.checksum(); +} + +void NfpDevice::UpdateRegisterInfoCrc() { +#pragma pack(push, 1) + struct CrcData { + Mii::Ver3StoreData mii; + u8 application_id_byte; + u8 unknown; + Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + }; + static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size"); +#pragma pack(pop) + + const CrcData crc_data{ + .mii = tag_data.owner_mii, + .application_id_byte = tag_data.application_id_byte, + .unknown = tag_data.unknown, + .mii_extension = tag_data.mii_extension, + .unknown2 = tag_data.unknown2, + }; - return ~crc; + boost::crc_32_type crc; + crc.process_bytes(&crc_data, sizeof(CrcData)); + tag_data.register_info_crc = crc.checksum(); } } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 06386401d..7f963730d 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -80,7 +80,7 @@ private: AmiiboDate GetAmiiboDate(s64 posix_time) const; u64 RemoveVersionByte(u64 application_id) const; void UpdateSettingsCrc(); - u32 CalculateCrc(std::span<const u8>); + void UpdateRegisterInfoCrc(); bool is_controller_set{}; int callback_key; @@ -92,8 +92,10 @@ private: Kernel::KEvent* deactivate_event = nullptr; Kernel::KEvent* availability_change_event = nullptr; + bool is_initalized{}; bool is_data_moddified{}; bool is_app_area_open{}; + bool is_plain_amiibo{}; TagProtocol allowed_protocols{}; s64 current_posix_time{}; MountTarget mount_target{MountTarget::None}; diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 142343d6e..70c878552 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -259,8 +259,9 @@ struct EncryptedAmiiboFile { u32_be application_area_id; // Encrypted Game id u8 application_id_byte; u8 unknown; - std::array<u32, 0x7> unknown2; - u32_be application_area_crc; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data }; static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); @@ -280,8 +281,9 @@ struct NTAG215File { u32_be application_area_id; u8 application_id_byte; u8 unknown; - std::array<u32, 0x7> unknown2; - u32_be application_area_crc; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array<u32, 0x5> unknown2; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data HashData hmac_tag; // Hash UniqueSerialNumber uid; // Unique serial number @@ -307,7 +309,8 @@ struct EncryptedNTAG215File { u32 CFG1; // Defines number of verification attempts NTAG215Password password; // Password data }; -static_assert(sizeof(EncryptedNTAG215File) == 0x21C, "EncryptedNTAG215File is an invalid size"); +static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File), + "EncryptedNTAG215File is an invalid size"); static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>, "EncryptedNTAG215File must be trivially copyable."); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index d2308fffc..453a965dc 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -304,8 +304,8 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8> Tegra::CommandList entries(params.num_entries); if (kickoff) { - system.Memory().ReadBlock(params.address, entries.command_lists.data(), - params.num_entries * sizeof(Tegra::CommandListHeader)); + system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), + params.num_entries * sizeof(Tegra::CommandListHeader)); } else { std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], params.num_entries * sizeof(Tegra::CommandListHeader)); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 7bcef105b..1ab51f10b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -105,8 +105,8 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, const auto object = nvmap.GetHandle(cmd_buffer.memory_id); ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); - system.Memory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), - cmdlist.size() * sizeof(u32)); + system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), + cmdlist.size() * sizeof(u32)); gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); } std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); |