From 6a1ecab2dde1db7d3183d9c98eda393341cca50b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 28 Aug 2023 00:54:39 +0200 Subject: [PATCH 1/6] Vulkan: Implement Depth Bias Control --- .../renderer_vulkan/vk_rasterizer.cpp | 25 ++++++++++++++++--- src/video_core/vulkan_common/vulkan_device.h | 15 +++++++++++ .../vulkan_common/vulkan_wrapper.cpp | 1 + src/video_core/vulkan_common/vulkan_wrapper.h | 13 ++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 01e76a82ca..0201c4d089 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1043,15 +1043,34 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM || regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM || regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM; - if (is_d24 && !device.SupportsD24DepthBuffer()) { + bool force_unorm = ([&] { + if (!is_d24 || device.SupportsD24DepthBuffer()) { + return false; + } + if (device.IsExtDepthBiasControlSupported()) { + return true; + } // the base formulas can be obtained from here: // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias const double rescale_factor = static_cast(1ULL << (32 - 24)) / (static_cast(0x1.ep+127)); units = static_cast(static_cast(units) * rescale_factor); - } + return false; + })(); scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, - factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) { + factor = regs.slope_scale_depth_bias, force_unorm, + precise = device.HasExactDepthBiasControl()](vk::CommandBuffer cmdbuf) { + if (force_unorm) { + VkDepthBiasRepresentationInfoEXT info{ + .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, + .pNext = nullptr, + .depthBiasRepresentation = + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT, + .depthBiasExact = precise ? VK_TRUE : VK_FALSE, + }; + cmdbuf.SetDepthBias(constant, clamp, factor, &info); + return; + } cmdbuf.SetDepthBias(constant, clamp, factor); }); } diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 488fdd3139..2063f58b5a 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -41,6 +41,7 @@ VK_DEFINE_HANDLE(VmaAllocator) // Define all features which may be used by the implementation and require an extension here. #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \ + FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \ FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ @@ -93,6 +94,7 @@ VK_DEFINE_HANDLE(VmaAllocator) // Define extensions where the absence of the extension may result in a degraded experience. #define FOR_EACH_VK_RECOMMENDED_EXTENSION(EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME) \ + EXTENSION_NAME(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) \ EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) \ @@ -143,6 +145,9 @@ VK_DEFINE_HANDLE(VmaAllocator) // Define features where the absence of the feature may result in a degraded experience. #define FOR_EACH_VK_RECOMMENDED_FEATURE(FEATURE_NAME) \ FEATURE_NAME(custom_border_color, customBorderColors) \ + FEATURE_NAME(depth_bias_control, depthBiasControl) \ + FEATURE_NAME(depth_bias_control, leastRepresentableValueForceUnormRepresentation) \ + FEATURE_NAME(depth_bias_control, depthBiasExact) \ FEATURE_NAME(extended_dynamic_state, extendedDynamicState) \ FEATURE_NAME(index_type_uint8, indexTypeUint8) \ FEATURE_NAME(primitive_topology_list_restart, primitiveTopologyListRestart) \ @@ -449,6 +454,12 @@ public: return extensions.depth_clip_control; } + /// Returns true if the device supports VK_EXT_depth_bias_control. + bool IsExtDepthBiasControlSupported() const { + return extensions.depth_bias_control && features.depth_bias_control.depthBiasControl && + features.depth_bias_control.leastRepresentableValueForceUnormRepresentation; + } + /// Returns true if the device supports VK_EXT_shader_viewport_index_layer. bool IsExtShaderViewportIndexLayerSupported() const { return extensions.shader_viewport_index_layer; @@ -600,6 +611,10 @@ public: return features.robustness2.nullDescriptor; } + bool HasExactDepthBiasControl() const { + return features.depth_bias_control.depthBiasExact; + } + u32 GetMaxVertexInputAttributes() const { return properties.properties.limits.maxVertexInputAttributes; } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index c3f388d895..97fb09d465 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -109,6 +109,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdPushDescriptorSetWithTemplateKHR); X(vkCmdSetBlendConstants); X(vkCmdSetDepthBias); + X(vkCmdSetDepthBias2EXT); X(vkCmdSetDepthBounds); X(vkCmdSetEvent); X(vkCmdSetScissor); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 049fa80387..679c2ffa85 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -222,6 +222,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; PFN_vkCmdSetDepthBias vkCmdSetDepthBias{}; + PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT{}; PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds{}; PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT{}; PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{}; @@ -1315,6 +1316,18 @@ public: dld->vkCmdSetDepthBias(handle, constant_factor, clamp, slope_factor); } + void SetDepthBias(float constant_factor, float clamp, float slope_factor, + VkDepthBiasRepresentationInfoEXT* extra) const noexcept { + VkDepthBiasInfoEXT info{ + .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT, + .pNext = extra, + .depthBiasConstantFactor = constant_factor, + .depthBiasClamp = clamp, + .depthBiasSlopeFactor = slope_factor, + }; + dld->vkCmdSetDepthBias2EXT(handle, &info); + } + void SetDepthBounds(float min_depth_bounds, float max_depth_bounds) const noexcept { dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds); } From b99f94a7ffab0698f209bf1b39d337940bc40e50 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 28 Aug 2023 01:37:40 +0200 Subject: [PATCH 2/6] Vulkan: add temporary workaround for AMDVLK --- src/common/settings.h | 2 ++ src/core/core.cpp | 7 +++++++ src/video_core/renderer_vulkan/vk_rasterizer.cpp | 3 +++ src/video_core/vulkan_common/vulkan_device.cpp | 7 +++++++ src/video_core/vulkan_common/vulkan_device.h | 3 +-- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 82ec9077ea..6f050c89d6 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -350,6 +350,8 @@ struct Values { linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; Setting enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", Category::RendererDebug}; + // TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control + bool renderer_amdvlk_depth_bias_workaround{}; // System SwitchableSetting language_index{linkage, diff --git a/src/core/core.cpp b/src/core/core.cpp index e8300cd05d..08cbb89783 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -381,6 +381,10 @@ struct System::Impl { room_member->SendGameInfo(game_info); } + // Workarounds: + // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK + Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL; + status = SystemResultStatus::Success; return status; } @@ -440,6 +444,9 @@ struct System::Impl { room_member->SendGameInfo(game_info); } + // Workarounds + Settings::values.renderer_amdvlk_depth_bias_workaround = false; + LOG_DEBUG(Core, "Shutdown OK"); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 0201c4d089..59b87807b4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1050,6 +1050,9 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { if (device.IsExtDepthBiasControlSupported()) { return true; } + if (!Settings::values.renderer_amdvlk_depth_bias_workaround) { + return false; + } // the base formulas can be obtained from here: // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias const double rescale_factor = diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6174170407..835a1338b5 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1051,6 +1051,13 @@ void Device::RemoveUnsuitableExtensions() { RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); + // VK_EXT_depth_bias_control + extensions.depth_bias_control = + features.depth_bias_control.depthBiasControl && + features.depth_bias_control.leastRepresentableValueForceUnormRepresentation; + RemoveExtensionFeatureIfUnsuitable(extensions.depth_bias_control, features.depth_bias_control, + VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME); + // VK_EXT_depth_clip_control extensions.depth_clip_control = features.depth_clip_control.depthClipControl; RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control, diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 2063f58b5a..eb314fe337 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -456,8 +456,7 @@ public: /// Returns true if the device supports VK_EXT_depth_bias_control. bool IsExtDepthBiasControlSupported() const { - return extensions.depth_bias_control && features.depth_bias_control.depthBiasControl && - features.depth_bias_control.leastRepresentableValueForceUnormRepresentation; + return extensions.depth_bias_control; } /// Returns true if the device supports VK_EXT_shader_viewport_index_layer. From 00a612eaea10dbeeb28daa223ed59f6216e890d0 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 25 Sep 2023 16:32:15 -0400 Subject: [PATCH 3/6] fsp-srv: add GetFileSystemAttribute --- src/core/hle/service/filesystem/fsp_srv.cpp | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 2492bbc160..c2054e8a0e 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -329,6 +329,7 @@ public: {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, {15, nullptr, "QueryEntry"}, + {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, }; RegisterHandlers(functions); } @@ -521,6 +522,46 @@ public: rb.PushRaw(vfs_timestamp); } + void GetFileSystemAttribute(HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + + struct FileSystemAttribute { + u8 dir_entry_name_length_max_defined; + u8 file_entry_name_length_max_defined; + u8 dir_path_name_length_max_defined; + u8 file_path_name_length_max_defined; + INSERT_PADDING_BYTES_NOINIT(0x5); + u8 utf16_dir_entry_name_length_max_defined; + u8 utf16_file_entry_name_length_max_defined; + u8 utf16_dir_path_name_length_max_defined; + u8 utf16_file_path_name_length_max_defined; + INSERT_PADDING_BYTES_NOINIT(0x18); + s32 dir_entry_name_length_max; + s32 file_entry_name_length_max; + s32 dir_path_name_length_max; + s32 file_path_name_length_max; + INSERT_PADDING_WORDS_NOINIT(0x5); + s32 utf16_dir_entry_name_length_max; + s32 utf16_file_entry_name_length_max; + s32 utf16_dir_path_name_length_max; + s32 utf16_file_path_name_length_max; + INSERT_PADDING_WORDS_NOINIT(0x18); + INSERT_PADDING_WORDS_NOINIT(0x1); + }; + static_assert(sizeof(FileSystemAttribute) == 0xc0, + "FileSystemAttribute has incorrect size"); + + FileSystemAttribute savedata_attribute{}; + savedata_attribute.dir_entry_name_length_max_defined = true; + savedata_attribute.file_entry_name_length_max_defined = true; + savedata_attribute.dir_entry_name_length_max = 0x40; + savedata_attribute.file_entry_name_length_max = 0x40; + + IPC::ResponseBuilder rb{ctx, 50}; + rb.Push(ResultSuccess); + rb.PushRaw(savedata_attribute); + } + private: VfsDirectoryServiceWrapper backend; SizeGetter size; From a29e26200f8cac773e008719201831edfb83eaee Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Tue, 26 Sep 2023 01:20:17 -0400 Subject: [PATCH 4/6] android: Remove ability to install xci files --- src/android/app/src/main/jni/native.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 71ef2833d5..7ae349e8ec 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -139,10 +139,6 @@ public: if (nsp->IsExtractedType()) { return InstallError; } - } else if (file_extension == "xci") { - jconst xci = - std::make_shared(m_vfs->OpenFile(filename, FileSys::Mode::Read)); - nsp = xci->GetSecurePartitionNSP(); } else { return ErrorFilenameExtension; } From feebdc9779f7934f6e6dcafd8e371db720b58215 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Tue, 26 Sep 2023 01:21:07 -0400 Subject: [PATCH 5/6] Qt: Remove ability to install xci files --- src/yuzu/main.cpp | 11 ++++------- src/yuzu/main.h | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index b1b6b9354c..adb7b332f9 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3113,10 +3113,9 @@ void GMainWindow::OnMenuInstallToNAND() { QFuture future; InstallResult result; - if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) || - file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { + if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { - future = QtConcurrent::run([this, &file] { return InstallNSPXCI(file); }); + future = QtConcurrent::run([this, &file] { return InstallNSP(file); }); while (!future.isFinished()) { QCoreApplication::processEvents(); @@ -3175,7 +3174,7 @@ void GMainWindow::OnMenuInstallToNAND() { ui->action_Install_File_NAND->setEnabled(true); } -InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { +InstallResult GMainWindow::InstallNSP(const QString& filename) { const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, std::size_t block_size) { if (src == nullptr || dest == nullptr) { @@ -3209,9 +3208,7 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { return InstallResult::Failure; } } else { - const auto xci = std::make_shared( - vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); - nsp = xci->GetSecurePartitionNSP(); + return InstallResult::Failure; } if (nsp->GetStatus() != Loader::ResultStatus::Success) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 53bedfab35..ba318eb11e 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -387,7 +387,7 @@ private: void RemoveCacheStorage(u64 program_id); bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, u64* selected_title_id, u8* selected_content_record_type); - InstallResult InstallNSPXCI(const QString& filename); + InstallResult InstallNSP(const QString& filename); InstallResult InstallNCA(const QString& filename); void MigrateConfigFiles(); void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, From e3f7e0255539e1c30518ab8b71b3506451953743 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 27 Sep 2023 23:34:03 -0600 Subject: [PATCH 6/6] service: mii: Fix reported bugs --- src/core/hle/service/am/applets/applet_mii_edit.cpp | 2 ++ src/core/hle/service/mii/mii_database_manager.cpp | 2 +- src/core/hle/service/mii/types/char_info.cpp | 2 +- src/core/hle/service/mii/types/core_data.cpp | 2 +- src/core/hle/service/nfc/common/device.cpp | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) 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 ff77830d25..50adc7c02e 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp @@ -145,6 +145,8 @@ void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) { .index{index}, }; + LOG_INFO(Input, "called, result={}, index={}", result, index); + std::vector out_data(sizeof(MiiEditAppletOutput)); std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput)); diff --git a/src/core/hle/service/mii/mii_database_manager.cpp b/src/core/hle/service/mii/mii_database_manager.cpp index c39898594a..0080b67051 100644 --- a/src/core/hle/service/mii/mii_database_manager.cpp +++ b/src/core/hle/service/mii/mii_database_manager.cpp @@ -168,7 +168,7 @@ Result DatabaseManager::FindIndex(s32& out_index, const Common::UUID& create_id, return ResultSuccess; } - for (std::size_t i = 0; i <= index; ++i) { + for (std::size_t i = 0; i < index; ++i) { if (database.Get(i).IsSpecial()) { continue; } diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp index c82186c73a..e90124af4c 100644 --- a/src/core/hle/service/mii/types/char_info.cpp +++ b/src/core/hle/service/mii/types/char_info.cpp @@ -37,7 +37,7 @@ void CharInfo::SetFromStoreData(const StoreData& store_data) { eyebrow_aspect = store_data.GetEyebrowAspect(); eyebrow_rotate = store_data.GetEyebrowRotate(); eyebrow_x = store_data.GetEyebrowX(); - eyebrow_y = store_data.GetEyebrowY(); + eyebrow_y = store_data.GetEyebrowY() + 3; nose_type = store_data.GetNoseType(); nose_scale = store_data.GetNoseScale(); nose_y = store_data.GetNoseY(); diff --git a/src/core/hle/service/mii/types/core_data.cpp b/src/core/hle/service/mii/types/core_data.cpp index 1068031e32..970c748cad 100644 --- a/src/core/hle/service/mii/types/core_data.cpp +++ b/src/core/hle/service/mii/types/core_data.cpp @@ -113,7 +113,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) { .values[MiiUtil::GetRandomValue(eyebrow_type_info.values_count)]); const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0}; - const auto eyebrow_y{race == Race::Asian ? 9 : 10}; + const auto eyebrow_y{race == Race::Asian ? 6 : 7}; const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6}; const auto eyebrow_rotate{ 32 - RawData::EyebrowRotateLookup[static_cast(data.eyebrow_type.Value())]}; diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 05951d8cbb..68c407f810 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -1374,7 +1374,7 @@ NFP::AmiiboName NfcDevice::GetAmiiboName(const NFP::AmiiboSettings& settings) co // Convert from utf16 to utf8 const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); - memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size() - 1); + memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size()); return amiibo_name; }