diff options
Diffstat (limited to '')
-rw-r--r-- | CMakeLists.txt | 2 | ||||
m--------- | externals/vcpkg | 0 | ||||
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/container_hash.h | 92 | ||||
-rw-r--r-- | src/common/zstd_compression.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/nfc/nfc_device.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/service/nfc/nfc_device.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/nfp/amiibo_crypto.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/nfp/amiibo_crypto.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_device.cpp | 50 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_device.h | 2 | ||||
-rw-r--r-- | src/core/hle/service/nfp/nfp_types.h | 3 | ||||
-rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/tests/common/container_hash.cpp | 44 | ||||
-rw-r--r-- | src/video_core/macro/macro.cpp | 6 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_scheduler.cpp | 11 | ||||
-rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 63 | ||||
-rw-r--r-- | vcpkg.json | 2 |
18 files changed, 249 insertions, 54 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6932b6fab..a6c43f401 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,7 +210,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) # ======================================================================= # Enforce the search mode of non-required packages for better and shorter failure messages -find_package(Boost 1.73.0 REQUIRED context) +find_package(Boost 1.79.0 REQUIRED context) find_package(enet 1.3 MODULE) find_package(fmt 9 REQUIRED) find_package(inih 52 MODULE COMPONENTS INIReader) diff --git a/externals/vcpkg b/externals/vcpkg -Subproject 9b22b40c6c61bf0da2d46346dd44a11e90972cc +Subproject a7b6122f6b6504d16d96117336a056269357993 diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 90805babe..c1d2b24a1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -38,6 +38,7 @@ add_library(common STATIC common_precompiled_headers.h common_types.h concepts.h + container_hash.h demangle.cpp demangle.h div_ceil.h diff --git a/src/common/container_hash.h b/src/common/container_hash.h new file mode 100644 index 000000000..a5e357745 --- /dev/null +++ b/src/common/container_hash.h @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: 2005-2014 Daniel James +// SPDX-FileCopyrightText: 2016 Austin Appleby +// SPDX-License-Identifier: BSL-1.0 + +#include <array> +#include <climits> +#include <cstdint> +#include <limits> +#include <type_traits> +#include <vector> + +namespace Common { + +namespace detail { + +template <typename T> + requires std::is_unsigned_v<T> +inline std::size_t HashValue(T val) { + const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits; + const unsigned int length = + (std::numeric_limits<T>::digits - 1) / static_cast<unsigned int>(size_t_bits); + + std::size_t seed = 0; + + for (unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) { + seed ^= static_cast<size_t>(val >> i) + (seed << 6) + (seed >> 2); + } + + seed ^= static_cast<size_t>(val) + (seed << 6) + (seed >> 2); + + return seed; +} + +template <size_t Bits> +struct HashCombineImpl { + template <typename T> + static inline T fn(T seed, T value) { + seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } +}; + +template <> +struct HashCombineImpl<64> { + static inline std::uint64_t fn(std::uint64_t h, std::uint64_t k) { + const std::uint64_t m = (std::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995; + const int r = 47; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Completely arbitrary number, to prevent 0's + // from hashing to 0. + h += 0xe6546b64; + + return h; + } +}; + +} // namespace detail + +template <typename T> +inline void HashCombine(std::size_t& seed, const T& v) { + seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, detail::HashValue(v)); +} + +template <typename It> +inline std::size_t HashRange(It first, It last) { + std::size_t seed = 0; + + for (; first != last; ++first) { + HashCombine<typename std::iterator_traits<It>::value_type>(seed, *first); + } + + return seed; +} + +template <typename T, size_t Size> +std::size_t HashValue(const std::array<T, Size>& v) { + return HashRange(v.cbegin(), v.cend()); +} + +template <typename T, typename Allocator> +std::size_t HashValue(const std::vector<T, Allocator>& v) { + return HashRange(v.cbegin(), v.cend()); +} + +} // namespace Common diff --git a/src/common/zstd_compression.cpp b/src/common/zstd_compression.cpp index b71a41b78..cb6ec171b 100644 --- a/src/common/zstd_compression.cpp +++ b/src/common/zstd_compression.cpp @@ -33,7 +33,7 @@ std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_siz std::vector<u8> DecompressDataZSTD(std::span<const u8> compressed) { const std::size_t decompressed_size = - ZSTD_getDecompressedSize(compressed.data(), compressed.size()); + ZSTD_getFrameContentSize(compressed.data(), compressed.size()); std::vector<u8> decompressed(decompressed_size); const std::size_t uncompressed_result_size = ZSTD_decompress( 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 bba862fb2..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{}; 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 268337d2e..607e70968 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -66,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; } @@ -111,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(); @@ -145,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() { @@ -155,6 +175,7 @@ void NfpDevice::Finalize() { StopDetection(); } device_state = DeviceState::Unavailable; + is_initalized = false; } Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { @@ -220,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"); @@ -244,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; diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 8813df998..7f963730d 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -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 b3599a513..70c878552 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -309,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/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index ae84408bc..39b774c98 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(tests common/bit_field.cpp common/cityhash.cpp + common/container_hash.cpp common/fibers.cpp common/host_memory.cpp common/param_package.cpp diff --git a/src/tests/common/container_hash.cpp b/src/tests/common/container_hash.cpp new file mode 100644 index 000000000..dc45565ef --- /dev/null +++ b/src/tests/common/container_hash.cpp @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <catch2/catch_test_macros.hpp> + +#include "common/common_types.h" +#include "common/container_hash.h" + +TEST_CASE("ContainerHash", "[common]") { + constexpr std::array<u8, 32> U8Values{ + 114, 10, 238, 189, 199, 242, 86, 96, 53, 193, 195, 247, 249, 56, 253, 61, + 205, 3, 172, 4, 210, 197, 43, 72, 103, 8, 99, 89, 5, 97, 68, 196, + }; + constexpr std::array<u16, 32> U16Values{ + 61586, 49151, 3313, 11641, 31695, 54795, 46764, 20965, 23287, 14039, 19265, + 49093, 58932, 22518, 27139, 42825, 57417, 54237, 48057, 14586, 42813, 32994, + 33970, 45501, 5619, 15895, 33227, 27509, 25391, 37275, 60218, 17599, + }; + constexpr std::array<u32, 32> U32Values{ + 3838402410U, 2029146863U, 1730869921U, 985528872U, 186773874U, 2094639868U, 3324775932U, + 1795512424U, 2571165571U, 3256934519U, 2358691590U, 2752682538U, 1484336451U, 378124520U, + 3463015699U, 3395942161U, 1263211979U, 3473632889U, 3039822212U, 2068707357U, 2223837919U, + 1823232191U, 1583884041U, 1264393380U, 4087566993U, 3188607101U, 3933680362U, 1464520765U, + 1786838406U, 1311734848U, 2773642241U, 3993641692U, + }; + constexpr std::array<u64, 32> U64Values{ + 5908025796157537817ULL, 10947547850358315100ULL, 844798943576724669ULL, + 7999662937458523703ULL, 4006550374705895164ULL, 1832550525423503632ULL, + 9323088254855830976ULL, 12028890075598379412ULL, 6021511300787826236ULL, + 7864675007938747948ULL, 18099387408859708806ULL, 6438638299316820708ULL, + 9029399285648501543ULL, 18195459433089960253ULL, 17214335092761966083ULL, + 5549347964591337833ULL, 14899526073304962015ULL, 5058883181561464475ULL, + 7436311795731206973ULL, 7535129567768649864ULL, 1287169596809258072ULL, + 8237671246353565927ULL, 1715230541978016153ULL, 8443157615068813300ULL, + 6098675262328527839ULL, 704652094100376853ULL, 1303411723202926503ULL, + 7808312933946424854ULL, 6863726670433556594ULL, 9870361541383217495ULL, + 9273671094091079488ULL, 17541434976160119010ULL, + }; + + REQUIRE(Common::HashValue(U8Values) == 5867183267093890552ULL); + REQUIRE(Common::HashValue(U16Values) == 9594135570564347135ULL); + REQUIRE(Common::HashValue(U32Values) == 13123757214696618460ULL); + REQUIRE(Common::HashValue(U64Values) == 7296500016546938380ULL); +} diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index 82ad0477d..905505ca1 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp @@ -6,7 +6,7 @@ #include <optional> #include <span> -#include <boost/container_hash/hash.hpp> +#include "common/container_hash.h" #include <fstream> #include "common/assert.h" @@ -89,7 +89,7 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { if (!mid_method.has_value()) { cache_info.lle_program = Compile(macro_code->second); - cache_info.hash = boost::hash_value(macro_code->second); + cache_info.hash = Common::HashValue(macro_code->second); if (Settings::values.dump_macros) { Dump(cache_info.hash, macro_code->second); } @@ -100,7 +100,7 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { code.resize(macro_cached.size() - rebased_method); std::memcpy(code.data(), macro_cached.data() + rebased_method, code.size() * sizeof(u32)); - cache_info.hash = boost::hash_value(code); + cache_info.hash = Common::HashValue(code); cache_info.lle_program = Compile(code); if (Settings::values.dump_macros) { Dump(cache_info.hash, code); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index c636a1625..b264e6ada 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -65,12 +65,13 @@ void Scheduler::WaitWorker() { DispatchWork(); // Ensure the queue is drained. - std::unique_lock ql{queue_mutex}; - event_cv.wait(ql, [this] { return work_queue.empty(); }); + { + std::unique_lock ql{queue_mutex}; + event_cv.wait(ql, [this] { return work_queue.empty(); }); + } // Now wait for execution to finish. - // This needs to be done in the same order as WorkerThread. - std::unique_lock el{execution_mutex}; + std::scoped_lock el{execution_mutex}; } void Scheduler::DispatchWork() { @@ -327,7 +328,7 @@ void Scheduler::AcquireNewChunk() { chunk = std::make_unique<CommandChunk>(); } else { // Otherwise, we can just take from the reserve. - chunk = std::make_unique<CommandChunk>(); + chunk = std::move(chunk_reserve.back()); chunk_reserve.pop_back(); } } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 8e8b9a5e6..858449af8 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1616,37 +1616,38 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s return; } auto& gpu_page_table = gpu_page_table_storage[*storage_id]; - ForEachGPUPage(gpu_addr, size, [this, gpu_page_table, &images, gpu_addr, size, func](u64 page) { - const auto it = gpu_page_table.find(page); - if (it == gpu_page_table.end()) { - if constexpr (BOOL_BREAK) { - return false; - } else { - return; - } - } - for (const ImageId image_id : it->second) { - Image& image = slot_images[image_id]; - if (True(image.flags & ImageFlagBits::Picked)) { - continue; - } - if (!image.OverlapsGPU(gpu_addr, size)) { - continue; - } - image.flags |= ImageFlagBits::Picked; - images.push_back(image_id); - if constexpr (BOOL_BREAK) { - if (func(image_id, image)) { - return true; - } - } else { - func(image_id, image); - } - } - if constexpr (BOOL_BREAK) { - return false; - } - }); + ForEachGPUPage(gpu_addr, size, + [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { + const auto it = gpu_page_table.find(page); + if (it == gpu_page_table.end()) { + if constexpr (BOOL_BREAK) { + return false; + } else { + return; + } + } + for (const ImageId image_id : it->second) { + Image& image = slot_images[image_id]; + if (True(image.flags & ImageFlagBits::Picked)) { + continue; + } + if (!image.OverlapsGPU(gpu_addr, size)) { + continue; + } + image.flags |= ImageFlagBits::Picked; + images.push_back(image_id); + if constexpr (BOOL_BREAK) { + if (func(image_id, image)) { + return true; + } + } else { + func(image_id, image); + } + } + if constexpr (BOOL_BREAK) { + return false; + } + }); for (const ImageId image_id : images) { slot_images[image_id].flags &= ~ImageFlagBits::Picked; } diff --git a/vcpkg.json b/vcpkg.json index fbadca0e6..0352dab77 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", "name": "yuzu", - "builtin-baseline": "9b22b40c6c61bf0da2d46346dd44a11e90972cc9", + "builtin-baseline": "acc3bcf76b84ae5041c86ab55fe138ae7b8255c7", "version": "1.0", "dependencies": [ "boost-algorithm", |