diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/code_set.h | 14 | ||||
-rw-r--r-- | src/core/hle/kernel/k_address_space_info.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 33 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.cpp | 23 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.h | 14 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process_page_table.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.h | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 14 | ||||
-rw-r--r-- | src/core/hle/service/am/applets/applet_cabinet.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.cpp | 12 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_server.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_server.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/ver3_store_data.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/nfc/common/device.cpp | 70 | ||||
-rw-r--r-- | src/core/hle/service/nfc/common/device.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/set/set_sys.cpp | 4 |
18 files changed, 182 insertions, 60 deletions
diff --git a/src/core/hle/kernel/code_set.h b/src/core/hle/kernel/code_set.h index af1af2b78..4d2d0098e 100644 --- a/src/core/hle/kernel/code_set.h +++ b/src/core/hle/kernel/code_set.h @@ -75,12 +75,26 @@ struct CodeSet final { return segments[2]; } +#ifdef HAS_NCE + Segment& PatchSegment() { + return patch_segment; + } + + const Segment& PatchSegment() const { + return patch_segment; + } +#endif + /// The overall data that backs this code set. Kernel::PhysicalMemory memory; /// The segments that comprise this code set. std::array<Segment, 3> segments; +#ifdef HAS_NCE + Segment patch_segment; +#endif + /// The entry point address for this code set. KProcessAddress entrypoint = 0; }; diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 32173e52b..23258071e 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp @@ -25,8 +25,8 @@ constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ { .bit_width = 36, .address = 2_GiB , .size = 64_GiB - 2_GiB , .type = KAddressSpaceInfo::Type::MapLarge, }, { .bit_width = 36, .address = Size_Invalid, .size = 8_GiB , .type = KAddressSpaceInfo::Type::Heap, }, { .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, }, -#ifdef ANDROID - // With Android, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region. +#ifdef HAS_NCE + // With NCE, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region. { .bit_width = 39, .address = 128_MiB , .size = 256_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, #else { .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 47dc8fd35..6691586ed 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -88,6 +88,22 @@ Result FlushDataCache(AddressType addr, u64 size) { R_SUCCEED(); } +constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission perm) { + Common::MemoryPermission perms{}; + if (True(perm & KMemoryPermission::UserRead)) { + perms |= Common::MemoryPermission::Read; + } + if (True(perm & KMemoryPermission::UserWrite)) { + perms |= Common::MemoryPermission::Write; + } +#ifdef HAS_NCE + if (True(perm & KMemoryPermission::UserExecute)) { + perms |= Common::MemoryPermission::Execute; + } +#endif + return perms; +} + } // namespace void KPageTableBase::MemoryRange::Open() { @@ -170,7 +186,8 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource* system_resource, KResourceLimit* resource_limit, - Core::Memory::Memory& memory) { + Core::Memory::Memory& memory, + KProcessAddress aslr_space_start) { // Calculate region extents. const size_t as_width = GetAddressSpaceWidth(as_type); const KProcessAddress start = 0; @@ -211,7 +228,8 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Heap); stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Stack); kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type::MapSmall); - m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type::Map39Bit); + m_code_region_start = m_address_space_start + aslr_space_start + + GetSpaceStart(KAddressSpaceInfo::Type::Map39Bit); m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit); m_alias_code_region_start = m_code_region_start; m_alias_code_region_end = m_code_region_end; @@ -5643,7 +5661,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a case OperationType::Map: { ASSERT(virt_addr != 0); ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); - m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr); + m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr, + ConvertToMemoryPermission(properties.perm)); // Open references to pages, if we should. if (this->IsHeapPhysicalAddress(phys_addr)) { @@ -5658,8 +5677,11 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a } case OperationType::ChangePermissions: case OperationType::ChangePermissionsAndRefresh: - case OperationType::ChangePermissionsAndRefreshAndFlush: + case OperationType::ChangePermissionsAndRefreshAndFlush: { + m_memory->ProtectRegion(*m_impl, virt_addr, num_pages * PageSize, + ConvertToMemoryPermission(properties.perm)); R_SUCCEED(); + } default: UNREACHABLE(); } @@ -5687,7 +5709,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const size_t size{node.GetNumPages() * PageSize}; // Map the pages. - m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress()); + m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(), + ConvertToMemoryPermission(properties.perm)); virt_addr += size; } diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index ee2c41e67..556d230b3 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -235,7 +235,8 @@ public: bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource* system_resource, - KResourceLimit* resource_limit, Core::Memory::Memory& memory); + KResourceLimit* resource_limit, Core::Memory::Memory& memory, + KProcessAddress aslr_space_start); void Finalize(); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 3cfb414e5..6c29eb72c 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -300,7 +300,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, - m_system_resource, res_limit, this->GetMemory())); + m_system_resource, res_limit, this->GetMemory(), 0)); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); @@ -332,7 +332,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa Result KProcess::Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, KResourceLimit* res_limit, - KMemoryManager::Pool pool) { + KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { ASSERT(res_limit != nullptr); // Set members. @@ -393,7 +393,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, m_system_resource, res_limit, - this->GetMemory())); + this->GetMemory(), aslr_space_start)); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); @@ -1128,7 +1128,7 @@ KProcess::KProcess(KernelCore& kernel) KProcess::~KProcess() = default; Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, - bool is_hbl) { + KProcessAddress aslr_space_start, bool is_hbl) { // Create a resource limit for the process. const auto physical_memory_size = m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application); @@ -1179,7 +1179,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: .name = {}, .version = {}, .program_id = metadata.GetTitleID(), - .code_address = code_address, + .code_address = code_address + GetInteger(aslr_space_start), .code_num_pages = static_cast<s32>(code_size / PageSize), .flags = flag, .reslimit = Svc::InvalidHandle, @@ -1193,7 +1193,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: // Initialize for application process. R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, - KMemoryManager::Pool::Application)); + KMemoryManager::Pool::Application, aslr_space_start)); // Assign remaining properties. m_is_hbl = is_hbl; @@ -1214,6 +1214,17 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute); ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read); ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); + +#ifdef HAS_NCE + if (Settings::IsNceEnabled()) { + auto& buffer = m_kernel.System().DeviceMemory().buffer; + const auto& code = code_set.CodeSegment(); + const auto& patch = code_set.PatchSegment(); + buffer.Protect(GetInteger(base_addr + code.addr), code.size, true, true, true); + buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, true, true, true); + ReprotectSegment(code_set.PatchSegment(), Svc::MemoryPermission::None); + } +#endif } bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 8339465fd..d8cd0fdde 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -120,6 +120,9 @@ private: std::atomic<s64> m_num_ipc_messages{}; std::atomic<s64> m_num_ipc_replies{}; std::atomic<s64> m_num_ipc_receives{}; +#ifdef HAS_NCE + std::unordered_map<u64, u64> m_post_handlers{}; +#endif private: Result StartTermination(); @@ -150,7 +153,8 @@ public: std::span<const u32> caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal); Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, - KResourceLimit* res_limit, KMemoryManager::Pool pool); + KResourceLimit* res_limit, KMemoryManager::Pool pool, + KProcessAddress aslr_space_start); void Exit(); const char* GetName() const { @@ -466,6 +470,12 @@ public: static void Switch(KProcess* cur_process, KProcess* next_process); +#ifdef HAS_NCE + std::unordered_map<u64, u64>& GetPostHandlers() noexcept { + return m_post_handlers; + } +#endif + public: // Attempts to insert a watchpoint into a free slot. Returns false if none are available. bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); @@ -479,7 +489,7 @@ public: public: Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, - bool is_hbl); + KProcessAddress aslr_space_start, bool is_hbl); void LoadModule(CodeSet code_set, KProcessAddress base_addr); diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h index b7ae5abd0..9e40f68bc 100644 --- a/src/core/hle/kernel/k_process_page_table.h +++ b/src/core/hle/kernel/k_process_page_table.h @@ -23,10 +23,11 @@ public: Result Initialize(Svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource* system_resource, - KResourceLimit* resource_limit, Core::Memory::Memory& memory) { - R_RETURN(m_page_table.InitializeForProcess(as_type, enable_aslr, enable_das_merge, - from_back, pool, code_address, code_size, - system_resource, resource_limit, memory)); + KResourceLimit* resource_limit, Core::Memory::Memory& memory, + KProcessAddress aslr_space_start) { + R_RETURN(m_page_table.InitializeForProcess( + as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, + system_resource, resource_limit, memory, aslr_space_start)); } void Finalize() { diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e1f80b04f..e9ca5dfca 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -655,6 +655,21 @@ public: return m_stack_top; } +public: + // TODO: This shouldn't be defined in kernel namespace + struct NativeExecutionParameters { + u64 tpidr_el0{}; + u64 tpidrro_el0{}; + void* native_context{}; + std::atomic<u32> lock{1}; + bool is_running{}; + u32 magic{Common::MakeMagic('Y', 'U', 'Z', 'U')}; + }; + + NativeExecutionParameters& GetNativeExecutionParameters() { + return m_native_execution_parameters; + } + private: KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key); @@ -914,6 +929,7 @@ private: ThreadWaitReasonForDebugging m_wait_reason_for_debugging{}; uintptr_t m_argument{}; KProcessAddress m_stack_top{}; + NativeExecutionParameters m_native_execution_parameters{}; public: using ConditionVariableThreadTreeType = ConditionVariableThreadTree; diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 5ee869fa2..073039825 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -1,8 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/settings.h" #include "core/arm/dynarmic/arm_dynarmic_32.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" +#ifdef HAS_NCE +#include "core/arm/nce/arm_nce.h" +#endif #include "core/core.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" @@ -14,7 +18,8 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) // TODO(bunnei): Initialization relies on a core being available. We may later replace this with - // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. + // an NCE interface or a 32-bit instance of Dynarmic. This should be abstracted out to a CPU + // manager. auto& kernel = system.Kernel(); m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( system, kernel.IsMulticore(), @@ -28,6 +33,13 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu PhysicalCore::~PhysicalCore() = default; void PhysicalCore::Initialize(bool is_64_bit) { +#if defined(HAS_NCE) + if (Settings::IsNceEnabled()) { + m_arm_interface = std::make_unique<Core::ARM_NCE>(m_system, m_system.Kernel().IsMulticore(), + m_core_index); + return; + } +#endif #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) auto& kernel = m_system.Kernel(); if (!is_64_bit) { diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 9d1960cb7..3906c0fa4 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -131,7 +131,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) nfp_device->DeleteApplicationArea(); break; case Service::NFP::CabinetMode::StartRestorer: - nfp_device->RestoreAmiibo(); + nfp_device->Restore(); break; case Service::NFP::CabinetMode::StartFormatter: nfp_device->Format(); diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 3bcf0ee9f..fcd973414 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -16,7 +16,8 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_} { + : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), + touchscreen_height(Layout::ScreenUndocked::Height) { static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size, "TouchSharedMemory is bigger than the shared memory"); shared_memory = std::construct_at( @@ -95,8 +96,8 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (id < active_fingers_count) { const auto& [active_x, active_y] = active_fingers[id].position; touch_entry.position = { - .x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width), - .y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height), + .x = static_cast<u16>(active_x * static_cast<float>(touchscreen_width)), + .y = static_cast<u16>(active_y * static_cast<float>(touchscreen_height)), }; touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; @@ -120,4 +121,9 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { shared_memory->touch_screen_lifo.WriteNextEntry(next_state); } +void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { + touchscreen_width = width; + touchscreen_height = height; +} + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index cd342ce91..79f026a81 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -28,6 +28,8 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; + void SetTouchscreenDimensions(u32 width, u32 height); + private: static constexpr std::size_t MAX_FINGERS = 16; @@ -53,5 +55,7 @@ private: Core::HID::EmulatedConsole* console = nullptr; std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; + u32 touchscreen_width; + u32 touchscreen_height; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 583142e35..a7d1578d9 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -208,6 +208,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r {1001, &IHidServer::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, {1002, &IHidServer::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"}, {1003, &IHidServer::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"}, + {1004, &IHidServer::SetTouchScreenResolution, "SetTouchScreenResolution"}, {2000, nullptr, "ActivateDigitizer"}, }; // clang-format on @@ -2363,6 +2364,21 @@ void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) { rb.Push(false); } +void IHidServer::SetTouchScreenResolution(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto width{rp.Pop<u32>()}; + const auto height{rp.Pop<u32>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + GetResourceManager()->GetTouchScreen()->SetTouchscreenDimensions(width, height); + + LOG_INFO(Service_HID, "called, width={}, height={}, applet_resource_user_id={}", width, height, + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + std::shared_ptr<ResourceManager> IHidServer::GetResourceManager() { resource_manager->Initialize(); return resource_manager; diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index eb2e8e7f4..cc7c4ebdd 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h @@ -141,6 +141,7 @@ private: void GetNpadCommunicationMode(HLERequestContext& ctx); void SetTouchScreenConfiguration(HLERequestContext& ctx); void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx); + void SetTouchScreenResolution(HLERequestContext& ctx); std::shared_ptr<ResourceManager> resource_manager; std::shared_ptr<HidFirmwareSettings> firmware_settings; diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp index a019cc9f7..c27646fcf 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.cpp +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp @@ -98,7 +98,7 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const { } void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { - version = 1; + version = 3; mii_information.gender.Assign(static_cast<u8>(store_data.GetGender())); mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor())); height = store_data.GetHeight(); diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index e7a00deb3..f97e5b44c 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -401,6 +401,12 @@ Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& time } Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { + bool is_corrupted = false; + + if (model_type != NFP::ModelType::Amiibo) { + return ResultInvalidArgument; + } + if (device_state != DeviceState::TagFound) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); return ResultWrongDeviceState; @@ -420,26 +426,32 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target if (is_plain_amiibo) { std::vector<u8> data(sizeof(NFP::NTAG215File)); memcpy(data.data(), &tag_data, sizeof(tag_data)); - WriteBackupData(tag_data.uid, data); - - device_state = DeviceState::TagMounted; - mount_target = mount_target_; - return ResultSuccess; } - if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { - bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); - LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); - return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; + if (!is_plain_amiibo && !NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { + LOG_ERROR(Service_NFP, "Can't decode amiibo"); + is_corrupted = true; } - std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); - WriteBackupData(encrypted_tag_data.uuid, data); + if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { + LOG_ERROR(Service_NFP, "Invalid mii data"); + is_corrupted = true; + } device_state = DeviceState::TagMounted; mount_target = mount_target_; + if (!is_corrupted && mount_target != NFP::MountTarget::Rom) { + std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); + memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + WriteBackupData(encrypted_tag_data.uuid, data); + } + + if (is_corrupted && mount_target != NFP::MountTarget::Rom) { + bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); + return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; + } + return ResultSuccess; } @@ -606,6 +618,17 @@ Result NfcDevice::Restore() { } } + // Restore mii data in case is corrupted by previous instances of yuzu + if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { + LOG_ERROR(Service_NFP, "Regenerating mii data"); + Mii::StoreData new_mii{}; + new_mii.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All); + new_mii.SetNickname({u'y', u'u', u'z', u'u', u'\0'}); + + tag_data.owner_mii.BuildFromStoreData(new_mii); + tag_data.mii_extension.SetFromStoreData(new_mii); + } + // Overwrite tag contents with backup and mount the tag tag_data = temporary_tag_data; encrypted_tag_data = temporary_encrypted_tag_data; @@ -851,25 +874,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe return Flush(); } -Result NfcDevice::RestoreAmiibo() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return ResultTagRemoved; - } - return ResultWrongDeviceState; - } - - if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return ResultWrongDeviceState; - } - - // TODO: Load amiibo from backup on system - LOG_ERROR(Service_NFP, "Not Implemented"); - return ResultSuccess; -} - Result NfcDevice::Format() { Result result = ResultSuccess; @@ -877,7 +881,9 @@ Result NfcDevice::Format() { result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); } - if (result.IsError()) { + // We are formatting all data. Corruption is not an issue. + if (result.IsError() && + (result != ResultCorruptedData && result != ResultCorruptedDataWithBackup)) { return result; } diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 0ed1ff34c..d8efe25ec 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h @@ -68,7 +68,6 @@ public: Result DeleteRegisterInfo(); Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); - Result RestoreAmiibo(); Result Format(); Result OpenApplicationArea(u32 access_id); diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index f5edfdc8b..48304e6d1 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -34,7 +34,9 @@ Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& nca = bis_system->GetEntry(FirmwareVersionSystemDataId, FileSys::ContentRecordType::Data); } if (nca) { - romfs = FileSys::ExtractRomFS(nca->GetRomFS()); + if (auto nca_romfs = nca->GetRomFS(); nca_romfs) { + romfs = FileSys::ExtractRomFS(nca_romfs); + } } if (!romfs) { romfs = FileSys::ExtractRomFS( |