diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 0168ff9cbf..338b89875c 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Tony Wasserka // SPDX-FileCopyrightText: 2014 Dolphin Emulator Project // SPDX-License-Identifier: BSD-3-Clause AND GPL-2.0-or-later @@ -83,25 +86,22 @@ */ #pragma pack(1) template + requires std::is_trivially_copyable_v struct BitField { private: // UnderlyingType is T for non-enum types and the underlying type of T if // T is an enumeration. Note that T is wrapped within an enable_if in the // former case to workaround compile errors which arise when using // std::underlying_type::type directly. - using UnderlyingType = typename std::conditional_t, std::underlying_type, - std::enable_if>::type; - + using UnderlyingType = typename std::conditional_t, std::underlying_type, std::enable_if>::type; // We store the value as the unsigned type to avoid undefined behaviour on value shifting using StorageType = std::make_unsigned_t; - using StorageTypeWithEndian = typename AddEndian::type; - public: /// Constants to allow limited introspection of fields if needed static constexpr std::size_t position = Position; static constexpr std::size_t bits = Bits; - static constexpr StorageType mask = (((StorageType)~0) >> (8 * sizeof(T) - bits)) << position; + static constexpr StorageType mask = (StorageType(~0) >> (CHAR_BIT * sizeof(T) - bits)) << position; /** * Formats a value by masking and shifting it according to the field parameters. A value @@ -109,21 +109,18 @@ public: * the results together. */ [[nodiscard]] static constexpr StorageType FormatValue(const T& value) { - return (static_cast(value) << position) & mask; + return (StorageType(value) << position) & mask; } - /** - * Extracts a value from the passed storage. In most situations prefer use the member functions - * (such as Value() or operator T), but this can be used to extract a value from a bitfield - * union in a constexpr context. - */ + /// @brief Extracts a value from the passed storage. In most situations prefer use the member functions + /// (such as Value() or operator T), but this can be used to extract a value from a bitfield + /// union in a constexpr context. [[nodiscard]] static constexpr T ExtractValue(const StorageType& storage) { if constexpr (std::numeric_limits::is_signed) { - std::size_t shift = 8 * sizeof(T) - bits; - return static_cast(static_cast(storage << (shift - position)) >> - shift); + std::size_t shift = CHAR_BIT * sizeof(T) - bits; + return T(UnderlyingType(storage << (shift - position)) >> shift); } else { - return static_cast((storage & mask) >> position); + return T((storage & mask) >> position); } } @@ -141,30 +138,14 @@ public: constexpr BitField(BitField&&) noexcept = default; constexpr BitField& operator=(BitField&&) noexcept = default; - constexpr void Assign(const T& value) { -#ifdef _MSC_VER - storage = static_cast((storage & ~mask) | FormatValue(value)); -#else - // Explicitly reload with memcpy to avoid compiler aliasing quirks - // regarding optimization: GCC/Clang clobber chained stores to - // different bitfields in the same struct with the last value. - StorageTypeWithEndian storage_; - std::memcpy(&storage_, &storage, sizeof(storage_)); - storage = static_cast((storage_ & ~mask) | FormatValue(value)); -#endif + constexpr void Assign(const T value) { + storage = StorageType((storage & ~mask) | FormatValue(value)); } [[nodiscard]] constexpr T Value() const { return ExtractValue(storage); } - template - [[nodiscard]] constexpr ConvertedToType As() const { - static_assert(!std::is_same_v, - "Unnecessary cast. Use Value() instead."); - return static_cast(Value()); - } - [[nodiscard]] constexpr operator T() const { return Value(); } @@ -176,13 +157,11 @@ public: private: StorageTypeWithEndian storage; - static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); - + static_assert(bits + position <= CHAR_BIT * sizeof(T), "Bitfield out of range"); // And, you know, just in case people specify something stupid like bits=position=0x80000000 - static_assert(position < 8 * sizeof(T), "Invalid position"); - static_assert(bits <= 8 * sizeof(T), "Invalid number of bits"); + static_assert(position < CHAR_BIT * sizeof(T), "Invalid position"); + static_assert(bits <= CHAR_BIT * sizeof(T), "Invalid number of bits"); static_assert(bits > 0, "Invalid number of bits"); - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable in a BitField"); }; #pragma pack() diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 13368b4392..c0ce872de8 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,46 +17,34 @@ namespace Common { /// Gets the size of a specified type T in bits. template + requires std::is_integral_v [[nodiscard]] constexpr std::size_t BitSize() { return sizeof(T) * CHAR_BIT; } -[[nodiscard]] constexpr u32 MostSignificantBit32(const u32 value) { - return 31U - static_cast(std::countl_zero(value)); -} - -[[nodiscard]] constexpr u32 MostSignificantBit64(const u64 value) { - return 63U - static_cast(std::countl_zero(value)); -} - -[[nodiscard]] constexpr u32 Log2Floor32(const u32 value) { - return MostSignificantBit32(value); -} - -[[nodiscard]] constexpr u32 Log2Floor64(const u64 value) { - return MostSignificantBit64(value); -} - -[[nodiscard]] constexpr u32 Log2Ceil32(const u32 value) { - const u32 log2_f = Log2Floor32(value); - return log2_f + static_cast((value ^ (1U << log2_f)) != 0U); +template + requires std::is_integral_v +[[nodiscard]] constexpr u32 MostSignificantBit(const T value) { + return (sizeof(T) * CHAR_BIT - 1) - std::countl_zero(value); } -[[nodiscard]] constexpr u32 Log2Ceil64(const u64 value) { - const u64 log2_f = Log2Floor64(value); - return static_cast(log2_f + static_cast((value ^ (1ULL << log2_f)) != 0ULL)); +template + requires std::is_integral_v +[[nodiscard]] constexpr T Log2Floor(const T value) { + return MostSignificantBit(value); } -template - requires std::is_unsigned_v -[[nodiscard]] constexpr bool IsPow2(T value) { - return std::has_single_bit(value); +template + requires std::is_integral_v +[[nodiscard]] constexpr T Log2Ceil(const T value) { + const T log2_f = Log2Floor(value); + return T(log2_f + T((value ^ (T(1ULL) << log2_f)) != T(0ULL))); } template requires std::is_integral_v [[nodiscard]] T NextPow2(T value) { - return static_cast(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); + return T(1ULL << (sizeof(T) * CHAR_BIT - std::countl_zero(value - 1U))); } template diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 639c2d0e0d..18e83d3381 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -8,12 +8,21 @@ #include #include - -#if !defined(ARCHITECTURE_x86_64) +#include #include // for exit -#endif #include "common/common_types.h" +#ifndef __cpp_lib_to_underlying +namespace std { +// https://en.cppreference.com/cpp/utility/to_underlying +template + requires std::is_enum_v +constexpr std::underlying_type_t to_underlying(T e) noexcept { + return std::underlying_type_t(e); +} +} +#endif + /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor. #define CONCAT2(x, y) DO_CONCAT2(x, y) #define DO_CONCAT2(x, y) x##y @@ -38,56 +47,43 @@ #define DECLARE_ENUM_FLAG_OPERATORS(type) \ [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(static_cast(a) | static_cast(b)); \ + return type(std::to_underlying(a) | std::to_underlying(b)); \ } \ [[nodiscard]] constexpr type operator&(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(static_cast(a) & static_cast(b)); \ + return type(std::to_underlying(a) & std::to_underlying(b)); \ } \ [[nodiscard]] constexpr type operator^(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(static_cast(a) ^ static_cast(b)); \ + return type(std::to_underlying(a) ^ std::to_underlying(b)); \ } \ [[nodiscard]] constexpr type operator<<(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(static_cast(a) << static_cast(b)); \ + return type(std::to_underlying(a) << std::to_underlying(b)); \ } \ [[nodiscard]] constexpr type operator>>(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(static_cast(a) >> static_cast(b)); \ + return type(std::to_underlying(a) >> std::to_underlying(b)); \ } \ - constexpr type& operator|=(type& a, type b) noexcept { \ - a = a | b; \ - return a; \ + constexpr type operator|=(type& a, type b) noexcept { \ + return a = a | b; \ } \ - constexpr type& operator&=(type& a, type b) noexcept { \ - a = a & b; \ - return a; \ + constexpr type operator&=(type& a, type b) noexcept { \ + return a = a & b; \ } \ - constexpr type& operator^=(type& a, type b) noexcept { \ - a = a ^ b; \ - return a; \ + constexpr type operator^=(type& a, type b) noexcept { \ + return a = a ^ b; \ } \ - constexpr type& operator<<=(type& a, type b) noexcept { \ - a = a << b; \ - return a; \ + constexpr type operator<<=(type& a, type b) noexcept { \ + return a = a << b; \ } \ - constexpr type& operator>>=(type& a, type b) noexcept { \ - a = a >> b; \ - return a; \ + constexpr type operator>>=(type& a, type b) noexcept { \ + return a = a >> b; \ } \ [[nodiscard]] constexpr type operator~(type key) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(~static_cast(key)); \ + return type(~std::to_underlying(key)); \ } \ [[nodiscard]] constexpr bool True(type key) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(key) != 0; \ + return std::to_underlying(key) != 0; \ } \ [[nodiscard]] constexpr bool False(type key) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(key) == 0; \ + return std::to_underlying(key) == 0; \ } #define YUZU_NON_COPYABLE(cls) \ @@ -104,10 +100,8 @@ namespace Common { return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; } -[[nodiscard]] constexpr u64 MakeMagic(char a, char b, char c, char d, char e, char f, char g, - char h) { - return u64(a) << 0 | u64(b) << 8 | u64(c) << 16 | u64(d) << 24 | u64(e) << 32 | u64(f) << 40 | - u64(g) << 48 | u64(h) << 56; +[[nodiscard]] constexpr u64 MakeMagic(char a, char b, char c, char d, char e, char f, char g, char h) { + return u64(a) << 0 | u64(b) << 8 | u64(c) << 16 | u64(d) << 24 | u64(e) << 32 | u64(f) << 40 | u64(g) << 48 | u64(h) << 56; } } // namespace Common diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 246c3db5d6..b1ccfbd18a 100644 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -277,13 +280,11 @@ public: * @returns Count of T data successfully read. */ template + requires std::is_trivially_copyable_v [[nodiscard]] size_t ReadSpan(std::span data) const { - static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); - if (!IsOpen()) { return 0; } - return std::fread(data.data(), sizeof(T), data.size(), file); } diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index e97854f514..10e53d3018 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,17 +23,15 @@ namespace Common { /// @tparam T Element type /// @tparam capacity Number of slots in ring buffer template + requires std::is_trivial_v class RingBuffer { /// A "slot" is made of a single `T`. static constexpr std::size_t slot_size = sizeof(T); - // T must be safely memcpy-able and have a trivial default constructor. - static_assert(std::is_trivial_v); // Ensure capacity is sensible. static_assert(capacity < (std::numeric_limits::max)() / 2); static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); // Ensure lock-free. static_assert(std::atomic_size_t::is_always_lock_free); - public: /// Pushes slots into the ring buffer /// @param new_slots Pointer to the slots to push diff --git a/src/common/typed_address.h b/src/common/typed_address.h index 4df48a99fb..f716accd03 100644 --- a/src/common/typed_address.h +++ b/src/common/typed_address.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,8 +33,8 @@ public: // Arithmetic operators. template + requires std::is_integral_v constexpr inline TypedAddress operator+(I rhs) const { - static_assert(std::is_integral_v); return m_address + rhs; } @@ -48,8 +51,8 @@ public: } template + requires std::is_integral_v constexpr inline TypedAddress operator-(I rhs) const { - static_assert(std::is_integral_v); return m_address - rhs; } @@ -66,15 +69,15 @@ public: } template + requires std::is_integral_v constexpr inline TypedAddress operator+=(I rhs) { - static_assert(std::is_integral_v); m_address += rhs; return *this; } template + requires std::is_integral_v constexpr inline TypedAddress operator-=(I rhs) { - static_assert(std::is_integral_v); m_address -= rhs; return *this; } @@ -89,8 +92,8 @@ public: } template + requires std::is_integral_v constexpr inline TypedAddress operator|=(I rhs) { - static_assert(std::is_integral_v); m_address |= rhs; return *this; } diff --git a/src/common/x64/xbyak.h b/src/common/x64/xbyak.h index e541215994..5288c5184f 100644 --- a/src/common/x64/xbyak.h +++ b/src/common/x64/xbyak.h @@ -268,8 +268,8 @@ constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) noexcept { } template + requires std::is_pointer_v inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { - static_assert(std::is_pointer_v, "Argument must be a (function) pointer."); uintptr_t addr = uintptr_t(f); if (IsWithin2G(uintptr_t(code.getCurr()), addr)) { code.call(f); diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp index 34d66456ee..719c3c3b8f 100644 --- a/src/core/crypto/aes_util.cpp +++ b/src/core/crypto/aes_util.cpp @@ -56,10 +56,9 @@ static inline const std::string GetCipherName(Mode mode, u32 key_size) { }; static EVP_CIPHER *GetCipher(Mode mode, u32 key_size) { - static auto fetch_cipher = [](Mode m, u32 k) { + auto const fetch_cipher = [](Mode m, u32 k) { return EVP_CIPHER_fetch(nullptr, GetCipherName(m, k).c_str(), nullptr); }; - static const struct { EVP_CIPHER* ctr_16 = fetch_cipher(Mode::CTR, 16); EVP_CIPHER* ecb_16 = fetch_cipher(Mode::ECB, 16); @@ -68,7 +67,6 @@ static EVP_CIPHER *GetCipher(Mode mode, u32 key_size) { EVP_CIPHER* ecb_32 = fetch_cipher(Mode::ECB, 32); EVP_CIPHER* xts_32 = fetch_cipher(Mode::XTS, 32); } ciphers = {}; - switch (mode) { case Mode::CTR: return key_size == 16 ? ciphers.ctr_16 : ciphers.ctr_32; @@ -79,17 +77,15 @@ static EVP_CIPHER *GetCipher(Mode mode, u32 key_size) { default: UNIMPLEMENTED(); } - return nullptr; } // TODO: WHY TEMPLATE??????? -template -Crypto::AESCipher::AESCipher(Key key, Mode mode) : ctx(std::make_unique()) { - +template +Crypto::AESCipher::AESCipher(Key key, Mode mode) : ctx(std::make_unique()) { ctx->encryption_context = EVP_CIPHER_CTX_new(); ctx->decryption_context = EVP_CIPHER_CTX_new(); - ctx->cipher = GetCipher(mode, KeySize); + ctx->cipher = GetCipher(mode, sizeof(Key)); if (ctx->cipher) { EVP_CIPHER_up_ref(ctx->cipher); } else { @@ -105,15 +101,15 @@ Crypto::AESCipher::AESCipher(Key key, Mode mode) : ctx(std::make_u EVP_CIPHER_CTX_set_padding(ctx->decryption_context, 0); } -template -AESCipher::~AESCipher() { +template +AESCipher::~AESCipher() { EVP_CIPHER_CTX_free(ctx->encryption_context); EVP_CIPHER_CTX_free(ctx->decryption_context); EVP_CIPHER_free(ctx->cipher); } -template -void AESCipher::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { +template +void AESCipher::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { auto* const context = op == Op::Encrypt ? ctx->encryption_context : ctx->decryption_context; if (size == 0) @@ -157,9 +153,8 @@ void AESCipher::Transcode(const u8* src, std::size_t size, u8* des std::memcpy(dest + whole_block_bytes, tail_buffer.data(), tail); } -template -void AESCipher::XTSTranscode(const u8* src, std::size_t size, u8* dest, - std::size_t sector_id, std::size_t sector_size, Op op) { +template +void AESCipher::XTSTranscode(const u8* src, std::size_t size, u8* dest, std::size_t sector_id, std::size_t sector_size, Op op) { ASSERT(size % sector_size == 0 && "XTS decryption size must be a multiple of sector size."); for (std::size_t i = 0; i < size; i += sector_size) { SetIV(CalculateNintendoTweak(sector_id++)); @@ -167,8 +162,8 @@ void AESCipher::XTSTranscode(const u8* src, std::size_t size, u8* } } -template -void AESCipher::SetIV(std::span data) { +template +void AESCipher::SetIV(std::span data) { const int ret_enc = EVP_CipherInit_ex(ctx->encryption_context, nullptr, nullptr, nullptr, data.data(), -1); const int ret_dec = EVP_CipherInit_ex(ctx->decryption_context, nullptr, nullptr, nullptr, data.data(), -1); ASSERT(ret_enc == 1 && ret_dec == 1 && "Failed to set IV on OpenSSL contexts"); diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h index a3de95e5e2..704e175d84 100644 --- a/src/core/crypto/aes_util.h +++ b/src/core/crypto/aes_util.h @@ -26,37 +26,30 @@ enum class Op { Decrypt, }; -template +template class AESCipher { - static_assert(std::is_same_v>, "Key must be std::array of u8."); - static_assert(KeySize == 0x10 || KeySize == 0x20, "KeySize must be 128 or 256."); - public: + static_assert(sizeof(Key) == 0x10 || sizeof(Key) == 0x20); AESCipher(Key key, Mode mode); ~AESCipher(); void SetIV(std::span data); template + requires std::is_trivially_copyable_v && std::is_trivially_copyable_v void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const { - static_assert(std::is_trivially_copyable_v && std::is_trivially_copyable_v, - "Transcode source and destination types must be trivially copyable."); Transcode(reinterpret_cast(src), size, reinterpret_cast(dest), op); } void Transcode(const u8* src, std::size_t size, u8* dest, Op op) const; template - void XTSTranscode(const Source* src, std::size_t size, Dest* dest, std::size_t sector_id, - std::size_t sector_size, Op op) { - static_assert(std::is_trivially_copyable_v && std::is_trivially_copyable_v, - "XTSTranscode source and destination types must be trivially copyable."); - XTSTranscode(reinterpret_cast(src), size, reinterpret_cast(dest), sector_id, - sector_size, op); + requires std::is_trivially_copyable_v && std::is_trivially_copyable_v + void XTSTranscode(const Source* src, std::size_t size, Dest* dest, std::size_t sector_id, std::size_t sector_size, Op op) { + XTSTranscode(reinterpret_cast(src), size, reinterpret_cast(dest), sector_id, sector_size, op); } - void XTSTranscode(const u8* src, std::size_t size, u8* dest, std::size_t sector_id, - std::size_t sector_size, Op op); + void XTSTranscode(const u8* src, std::size_t size, u8* dest, std::size_t sector_id, std::size_t sector_size, Op op); private: std::unique_ptr ctx; diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 68692c178e..4c5732a155 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -35,70 +35,56 @@ namespace { constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; -using Common::AsArray; - constexpr std::array>, 30> s128_file_id{{ {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, - {"eticket_rsa_kek_source", - {S128KeyType::Source, static_cast(SourceKeyType::ETicketKek), 0}}, - {"eticket_rsa_kekek_source", - {S128KeyType::Source, static_cast(SourceKeyType::ETicketKekek), 0}}, - {"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast(RSAKekType::Mask0), 0}}, - {"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast(RSAKekType::Seed3), 0}}, - {"rsa_oaep_kek_generation_source", - {S128KeyType::Source, static_cast(SourceKeyType::RSAOaepKekGeneration), 0}}, - {"sd_card_kek_source", {S128KeyType::Source, static_cast(SourceKeyType::SDKek), 0}}, - {"aes_kek_generation_source", - {S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration), 0}}, - {"aes_key_generation_source", - {S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration), 0}}, - {"package2_key_source", {S128KeyType::Source, static_cast(SourceKeyType::Package2), 0}}, - {"master_key_source", {S128KeyType::Source, static_cast(SourceKeyType::Master), 0}}, - {"header_kek_source", {S128KeyType::Source, static_cast(SourceKeyType::HeaderKek), 0}}, - {"key_area_key_application_source", - {S128KeyType::Source, static_cast(SourceKeyType::KeyAreaKey), - static_cast(KeyAreaKeyType::Application)}}, - {"key_area_key_ocean_source", - {S128KeyType::Source, static_cast(SourceKeyType::KeyAreaKey), - static_cast(KeyAreaKeyType::Ocean)}}, - {"key_area_key_system_source", - {S128KeyType::Source, static_cast(SourceKeyType::KeyAreaKey), - static_cast(KeyAreaKeyType::System)}}, - {"titlekek_source", {S128KeyType::Source, static_cast(SourceKeyType::Titlekek), 0}}, - {"keyblob_mac_key_source", - {S128KeyType::Source, static_cast(SourceKeyType::KeyblobMAC), 0}}, + {"eticket_rsa_kek_source", {S128KeyType::Source, u64(SourceKeyType::ETicketKek), 0}}, + {"eticket_rsa_kekek_source", {S128KeyType::Source, u64(SourceKeyType::ETicketKekek), 0}}, + {"rsa_kek_mask_0", {S128KeyType::RSAKek, u64(RSAKekType::Mask0), 0}}, + {"rsa_kek_seed_3", {S128KeyType::RSAKek, u64(RSAKekType::Seed3), 0}}, + {"rsa_oaep_kek_generation_source", {S128KeyType::Source, u64(SourceKeyType::RSAOaepKekGeneration), 0}}, + {"sd_card_kek_source", {S128KeyType::Source, u64(SourceKeyType::SDKek), 0}}, + {"aes_kek_generation_source", {S128KeyType::Source, u64(SourceKeyType::AESKekGeneration), 0}}, + {"aes_key_generation_source", {S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration), 0}}, + {"package2_key_source", {S128KeyType::Source, u64(SourceKeyType::Package2), 0}}, + {"master_key_source", {S128KeyType::Source, u64(SourceKeyType::Master), 0}}, + {"header_kek_source", {S128KeyType::Source, u64(SourceKeyType::HeaderKek), 0}}, + {"key_area_key_application_source", {S128KeyType::Source, u64(SourceKeyType::KeyAreaKey), u64(KeyAreaKeyType::Application)}}, + {"key_area_key_ocean_source", {S128KeyType::Source, u64(SourceKeyType::KeyAreaKey), u64(KeyAreaKeyType::Ocean)}}, + {"key_area_key_system_source", {S128KeyType::Source, u64(SourceKeyType::KeyAreaKey), u64(KeyAreaKeyType::System)}}, + {"titlekek_source", {S128KeyType::Source, u64(SourceKeyType::Titlekek), 0}}, + {"keyblob_mac_key_source", {S128KeyType::Source, u64(SourceKeyType::KeyblobMAC), 0}}, {"tsec_key", {S128KeyType::TSEC, 0, 0}}, {"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}}, {"sd_seed", {S128KeyType::SDSeed, 0, 0}}, - {"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast(BISKeyType::Crypto)}}, - {"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast(BISKeyType::Tweak)}}, - {"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast(BISKeyType::Crypto)}}, - {"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast(BISKeyType::Tweak)}}, - {"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast(BISKeyType::Crypto)}}, - {"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast(BISKeyType::Tweak)}}, - {"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast(BISKeyType::Crypto)}}, - {"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast(BISKeyType::Tweak)}}, + {"bis_key_0_crypt", {S128KeyType::BIS, 0, u64(BISKeyType::Crypto)}}, + {"bis_key_0_tweak", {S128KeyType::BIS, 0, u64(BISKeyType::Tweak)}}, + {"bis_key_1_crypt", {S128KeyType::BIS, 1, u64(BISKeyType::Crypto)}}, + {"bis_key_1_tweak", {S128KeyType::BIS, 1, u64(BISKeyType::Tweak)}}, + {"bis_key_2_crypt", {S128KeyType::BIS, 2, u64(BISKeyType::Crypto)}}, + {"bis_key_2_tweak", {S128KeyType::BIS, 2, u64(BISKeyType::Tweak)}}, + {"bis_key_3_crypt", {S128KeyType::BIS, 3, u64(BISKeyType::Crypto)}}, + {"bis_key_3_tweak", {S128KeyType::BIS, 3, u64(BISKeyType::Tweak)}}, {"header_kek", {S128KeyType::HeaderKek, 0, 0}}, {"sd_card_kek", {S128KeyType::SDKek, 0, 0}}, }}; auto Find128ByName(std::string_view name) { - return std::find_if(s128_file_id.begin(), s128_file_id.end(), - [&name](const auto& pair) { return pair.first == name; }); + return std::find_if(s128_file_id.begin(), s128_file_id.end(), [&name](const auto& pair) { + return pair.first == name; + }); } constexpr std::array>, 6> s256_file_id{{ {"header_key", {S256KeyType::Header, 0, 0}}, - {"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast(SDKeyType::Save), 0}}, - {"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast(SDKeyType::NCA), 0}}, + {"sd_card_save_key_source", {S256KeyType::SDKeySource, u64(SDKeyType::Save), 0}}, + {"sd_card_nca_key_source", {S256KeyType::SDKeySource, u64(SDKeyType::NCA), 0}}, {"header_key_source", {S256KeyType::HeaderSource, 0, 0}}, - {"sd_card_save_key", {S256KeyType::SDKey, static_cast(SDKeyType::Save), 0}}, - {"sd_card_nca_key", {S256KeyType::SDKey, static_cast(SDKeyType::NCA), 0}}, + {"sd_card_save_key", {S256KeyType::SDKey, u64(SDKeyType::Save), 0}}, + {"sd_card_nca_key", {S256KeyType::SDKey, u64(SDKeyType::NCA), 0}}, }}; auto Find256ByName(std::string_view name) { - return std::find_if(s256_file_id.begin(), s256_file_id.end(), - [&name](const auto& pair) { return pair.first == name; }); + return std::find_if(s256_file_id.begin(), s256_file_id.end(), [&name](const auto& pair) { return pair.first == name; }); } using KeyArray = std::array, std::string_view>, 7>; @@ -107,7 +93,7 @@ constexpr KeyArray KEYS_VARIABLE_LENGTH{{ {{S128KeyType::Package1, 0}, "package1_key_"}, {{S128KeyType::Package2, 0}, "package2_key_"}, {{S128KeyType::Titlekek, 0}, "titlekek_"}, - {{S128KeyType::Source, static_cast(SourceKeyType::Keyblob)}, "keyblob_key_source_"}, + {{S128KeyType::Source, u64(SourceKeyType::Keyblob)}, "keyblob_key_source_"}, {{S128KeyType::Keyblob, 0}, "keyblob_key_"}, {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, }}; @@ -152,49 +138,39 @@ bool Ticket::IsValid() const { } SignatureType Ticket::GetSignatureType() const { - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->sig_type; - } - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->sig_type; - } - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->sig_type; - } - throw std::bad_variant_access{}; + UNREACHABLE(); } TicketData& Ticket::GetData() { - if (auto* ticket = std::get_if(&data)) { + if (auto* ticket = std::get_if(&data)) return ticket->data; - } - if (auto* ticket = std::get_if(&data)) { + if (auto* ticket = std::get_if(&data)) return ticket->data; - } - if (auto* ticket = std::get_if(&data)) { + if (auto* ticket = std::get_if(&data)) return ticket->data; - } - throw std::bad_variant_access{}; + UNREACHABLE(); } const TicketData& Ticket::GetData() const { - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->data; - } - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->data; - } - if (const auto* ticket = std::get_if(&data)) { + if (const auto* ticket = std::get_if(&data)) return ticket->data; - } - throw std::bad_variant_access{}; + UNREACHABLE(); } u64 Ticket::GetSize() const { const auto sig_type = GetSignatureType(); - return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) + - GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData); + return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) + GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData); } Ticket Ticket::SynthesizeCommon(Key128 title_key, const std::array& rights_id) { @@ -222,8 +198,7 @@ Ticket Ticket::Read(std::span raw_data) { // just make sure we have at least the bare minimum of data to work with. SignatureType sig_type; if (raw_data.size() < sizeof(SignatureType)) { - LOG_WARNING(Crypto, "Attempted to parse ticket buffer with invalid size {}.", - raw_data.size()); + LOG_WARNING(Crypto, "Attempted to parse ticket buffer with invalid size {}.", raw_data.size()); return Ticket{std::monostate()}; } std::memcpy(&sig_type, raw_data.data(), sizeof(sig_type)); @@ -255,17 +230,14 @@ Ticket Ticket::Read(std::span raw_data) { Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) { Key128 out{}; - AESCipher cipher1(master, Mode::ECB); cipher1.Transcode(kek_seed.data(), kek_seed.size(), out.data(), Op::Decrypt); AESCipher cipher2(out, Mode::ECB); cipher2.Transcode(source.data(), source.size(), out.data(), Op::Decrypt); - if (key_seed != Key128{}) { AESCipher cipher3(out, Mode::ECB); cipher3.Transcode(key_seed.data(), key_seed.size(), out.data(), Op::Decrypt); } - return out; } @@ -280,16 +252,13 @@ Key128 DeriveKeyblobKey(const Key128& sbk, const Key128& tsec, Key128 source) { Key128 DeriveMasterKey(const std::array& keyblob, const Key128& master_source) { Key128 master_root; std::memcpy(master_root.data(), keyblob.data(), sizeof(Key128)); - AESCipher master_cipher(master_root, Mode::ECB); - Key128 master{}; master_cipher.Transcode(master_source.data(), master_source.size(), master.data(), Op::Decrypt); return master; } -std::array DecryptKeyblob(const std::array& encrypted_keyblob, - const Key128& key) { +std::array DecryptKeyblob(const std::array& encrypted_keyblob, const Key128& key) { std::array keyblob; AESCipher cipher(key, Mode::CTR); cipher.SetIV(std::vector(encrypted_keyblob.data() + 0x10, encrypted_keyblob.data() + 0x20)); @@ -298,61 +267,39 @@ std::array DecryptKeyblob(const std::array& encrypted_keyblob, } void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) { - const auto kek_generation_source = - GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration)); - const auto key_generation_source = - GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration)); - + const auto kek_generation_source = GetKey(S128KeyType::Source, u64(SourceKeyType::AESKekGeneration)); + const auto key_generation_source = GetKey(S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration)); if (HasKey(S128KeyType::Master, crypto_revision)) { - for (auto kak_type : - {KeyAreaKeyType::Application, KeyAreaKeyType::Ocean, KeyAreaKeyType::System}) { - if (HasKey(S128KeyType::Source, static_cast(SourceKeyType::KeyAreaKey), - static_cast(kak_type))) { - const auto source = - GetKey(S128KeyType::Source, static_cast(SourceKeyType::KeyAreaKey), - static_cast(kak_type)); - const auto kek = - GenerateKeyEncryptionKey(source, GetKey(S128KeyType::Master, crypto_revision), - kek_generation_source, key_generation_source); - SetKey(S128KeyType::KeyArea, kek, crypto_revision, static_cast(kak_type)); + for (auto kak_type : {KeyAreaKeyType::Application, KeyAreaKeyType::Ocean, KeyAreaKeyType::System}) { + if (HasKey(S128KeyType::Source, u64(SourceKeyType::KeyAreaKey), u64(kak_type))) { + const auto source = GetKey(S128KeyType::Source, u64(SourceKeyType::KeyAreaKey), u64(kak_type)); + const auto kek = GenerateKeyEncryptionKey(source, GetKey(S128KeyType::Master, crypto_revision), kek_generation_source, key_generation_source); + SetKey(S128KeyType::KeyArea, kek, crypto_revision, u64(kak_type)); } } - AESCipher master_cipher(GetKey(S128KeyType::Master, crypto_revision), Mode::ECB); for (auto key_type : {SourceKeyType::Titlekek, SourceKeyType::Package2}) { - if (HasKey(S128KeyType::Source, static_cast(key_type))) { + if (HasKey(S128KeyType::Source, u64(key_type))) { Key128 key{}; - master_cipher.Transcode( - GetKey(S128KeyType::Source, static_cast(key_type)).data(), key.size(), - key.data(), Op::Decrypt); - SetKey(key_type == SourceKeyType::Titlekek ? S128KeyType::Titlekek - : S128KeyType::Package2, - key, crypto_revision); + master_cipher.Transcode(GetKey(S128KeyType::Source, u64(key_type)).data(), key.size(), key.data(), Op::Decrypt); + SetKey(key_type == SourceKeyType::Titlekek ? S128KeyType::Titlekek : S128KeyType::Package2, key, crypto_revision); } } } } void KeyManager::DeriveETicketRSAKey() { - if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) { - return; + if (eticket_extended_kek != std::array{} && HasKey(S128KeyType::ETicketRSAKek)) { + const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); + std::vector extended_iv(eticket_extended_kek.begin(), eticket_extended_kek.begin() + 0x10); + std::array extended_dec{}; + AESCipher rsa_1(eticket_final, Mode::CTR); + rsa_1.SetIV(extended_iv); + rsa_1.Transcode(eticket_extended_kek.data() + 0x10, eticket_extended_kek.size() - 0x10, extended_dec.data(), Op::Decrypt); + std::memcpy(eticket_rsa_keypair.decryption_key.data(), extended_dec.data(), eticket_rsa_keypair.decryption_key.size()); + std::memcpy(eticket_rsa_keypair.modulus.data(), extended_dec.data() + 0x100, eticket_rsa_keypair.modulus.size()); + std::memcpy(eticket_rsa_keypair.exponent.data(), extended_dec.data() + 0x200, eticket_rsa_keypair.exponent.size()); } - - const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); - - std::vector extended_iv(eticket_extended_kek.begin(), eticket_extended_kek.begin() + 0x10); - std::array extended_dec{}; - AESCipher rsa_1(eticket_final, Mode::CTR); - rsa_1.SetIV(extended_iv); - rsa_1.Transcode(eticket_extended_kek.data() + 0x10, eticket_extended_kek.size() - 0x10, - extended_dec.data(), Op::Decrypt); - - std::memcpy(eticket_rsa_keypair.decryption_key.data(), extended_dec.data(), - eticket_rsa_keypair.decryption_key.size()); - std::memcpy(eticket_rsa_keypair.modulus.data(), extended_dec.data() + 0x100, - eticket_rsa_keypair.modulus.size()); - std::memcpy(eticket_rsa_keypair.exponent.data(), extended_dec.data() + 0x200, - eticket_rsa_keypair.exponent.size()); } Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) { @@ -363,78 +310,57 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) } std::optional DeriveSDSeed() { - const auto system_save_43_path = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000043"; - const Common::FS::IOFile save_43{system_save_43_path, Common::FS::FileAccessMode::Read, - Common::FS::FileType::BinaryFile}; - - if (!save_43.IsOpen()) { - return std::nullopt; - } - - const auto sd_private_path = - Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir) / "Nintendo/Contents/private"; - - const Common::FS::IOFile sd_private{sd_private_path, Common::FS::FileAccessMode::Read, - Common::FS::FileType::BinaryFile}; - - if (!sd_private.IsOpen()) { - return std::nullopt; - } - - std::array private_seed{}; - if (sd_private.Read(private_seed) != private_seed.size()) { - return std::nullopt; - } - - std::array buffer{}; - s64 offset = 0; - for (; offset + 0x10 < static_cast(save_43.GetSize()); ++offset) { - if (!save_43.Seek(offset)) { - return std::nullopt; - } + const auto system_save_43_path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000043"; + const Common::FS::IOFile save_43{system_save_43_path, Common::FS::FileAccessMode::Read, Common::FS::FileType::BinaryFile}; + if (save_43.IsOpen()) { + const auto sd_private_path = Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir) / "Nintendo/Contents/private"; + const Common::FS::IOFile sd_private{sd_private_path, Common::FS::FileAccessMode::Read, Common::FS::FileType::BinaryFile}; + if (sd_private.IsOpen()) { + std::array private_seed{}; + if (sd_private.Read(private_seed) == private_seed.size()) { + std::array buffer{}; + s64 offset = 0; + for (; offset + 0x10 < s64(save_43.GetSize()); ++offset) { + if (!save_43.Seek(offset)) { + return std::nullopt; + } - if (save_43.Read(buffer) != buffer.size()) { - return std::nullopt; - } + if (save_43.Read(buffer) != buffer.size()) { + return std::nullopt; + } - if (buffer == private_seed) { - break; + if (buffer == private_seed) { + break; + } + } + if (save_43.Seek(offset + 0x10)) { + Key128 seed{}; + if (save_43.Read(seed) == seed.size()) { + return seed; + } + } + } } } - - if (!save_43.Seek(offset + 0x10)) { - return std::nullopt; - } - - Key128 seed{}; - if (save_43.Read(seed) != seed.size()) { - return std::nullopt; - } - - return seed; + return std::nullopt; } Loader::ResultStatus DeriveSDKeys(std::array& sd_keys, KeyManager& keys) { - if (!keys.HasKey(S128KeyType::Source, static_cast(SourceKeyType::SDKek))) { + if (!keys.HasKey(S128KeyType::Source, u64(SourceKeyType::SDKek))) { return Loader::ResultStatus::ErrorMissingSDKEKSource; } - if (!keys.HasKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration))) { + if (!keys.HasKey(S128KeyType::Source, u64(SourceKeyType::AESKekGeneration))) { return Loader::ResultStatus::ErrorMissingAESKEKGenerationSource; } - if (!keys.HasKey(S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration))) { + if (!keys.HasKey(S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration))) { return Loader::ResultStatus::ErrorMissingAESKeyGenerationSource; } - const auto sd_kek_source = - keys.GetKey(S128KeyType::Source, static_cast(SourceKeyType::SDKek)); - const auto aes_kek_gen = - keys.GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration)); - const auto aes_key_gen = - keys.GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration)); + const auto sd_kek_source = keys.GetKey(S128KeyType::Source, u64(SourceKeyType::SDKek)); + const auto aes_kek_gen = keys.GetKey(S128KeyType::Source, u64(SourceKeyType::AESKekGeneration)); + const auto aes_key_gen = keys.GetKey(S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration)); const auto master_00 = keys.GetKey(S128KeyType::Master); - const auto sd_kek = - GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen); + const auto sd_kek = GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen); keys.SetKey(S128KeyType::SDKek, sd_kek); if (!keys.HasKey(S128KeyType::SDSeed)) { @@ -442,16 +368,16 @@ Loader::ResultStatus DeriveSDKeys(std::array& sd_keys, KeyManager& ke } const auto sd_seed = keys.GetKey(S128KeyType::SDSeed); - if (!keys.HasKey(S256KeyType::SDKeySource, static_cast(SDKeyType::Save))) { + if (!keys.HasKey(S256KeyType::SDKeySource, u64(SDKeyType::Save))) { return Loader::ResultStatus::ErrorMissingSDSaveKeySource; } - if (!keys.HasKey(S256KeyType::SDKeySource, static_cast(SDKeyType::NCA))) { + if (!keys.HasKey(S256KeyType::SDKeySource, u64(SDKeyType::NCA))) { return Loader::ResultStatus::ErrorMissingSDNCAKeySource; } std::array sd_key_sources{ - keys.GetKey(S256KeyType::SDKeySource, static_cast(SDKeyType::Save)), - keys.GetKey(S256KeyType::SDKeySource, static_cast(SDKeyType::NCA)), + keys.GetKey(S256KeyType::SDKeySource, u64(SDKeyType::Save)), + keys.GetKey(S256KeyType::SDKeySource, u64(SDKeyType::NCA)), }; // Combine sources and seed @@ -464,15 +390,13 @@ Loader::ResultStatus DeriveSDKeys(std::array& sd_keys, KeyManager& ke AESCipher cipher(sd_kek, Mode::ECB); // The transform manipulates sd_keys as part of the Transcode, so the return/output is // unnecessary. This does not alter sd_keys_sources. - std::transform(sd_key_sources.begin(), sd_key_sources.end(), sd_keys.begin(), - sd_key_sources.begin(), [&cipher](const Key256& source, Key256& out) { - cipher.Transcode(source.data(), source.size(), out.data(), Op::Decrypt); - return source; ///< Return unaltered source to satisfy output requirement. - }); - - keys.SetKey(S256KeyType::SDKey, sd_keys[0], static_cast(SDKeyType::Save)); - keys.SetKey(S256KeyType::SDKey, sd_keys[1], static_cast(SDKeyType::NCA)); + std::transform(sd_key_sources.begin(), sd_key_sources.end(), sd_keys.begin(), sd_key_sources.begin(), [&cipher](const Key256& source, Key256& out) { + cipher.Transcode(source.data(), source.size(), out.data(), Op::Decrypt); + return source; ///< Return unaltered source to satisfy output requirement. + }); + keys.SetKey(S256KeyType::SDKey, sd_keys[0], u64(SDKeyType::Save)); + keys.SetKey(S256KeyType::SDKey, sd_keys[1], u64(SDKeyType::NCA)); return Loader::ResultStatus::Success; } @@ -503,11 +427,9 @@ std::vector GetTicketblob(const Common::FS::IOFile& ticket_save) { } template -static std::array operator^(const std::array& lhs, - const std::array& rhs) { +static std::array operator^(const std::array& lhs, const std::array& rhs) { std::array out; - std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), - [](u8 lhs_elem, u8 rhs_elem) { return u8(lhs_elem ^ rhs_elem); }); + std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), [](u8 lhs_elem, u8 rhs_elem) { return u8(lhs_elem ^ rhs_elem); }); return out; } @@ -661,8 +583,7 @@ void KeyManager::ReloadKeys() { static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { if (base.size() < begin + length) return false; - return std::all_of(base.begin() + begin, base.begin() + begin + length, - [](u8 c) { return std::isxdigit(c); }); + return std::all_of(base.begin() + begin, base.begin() + begin + length, [](u8 c) { return std::isxdigit(c); }); } void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys) { @@ -673,101 +594,90 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti std::ifstream file; Common::FS::OpenFileStream(file, file_path, std::ios_base::in); - if (!file.is_open()) { - return; - } - - std::string line; - while (std::getline(file, line)) { - std::vector out; - std::stringstream stream(line); - std::string item; - while (std::getline(stream, item, '=')) { - out.push_back(std::move(item)); - } - - if (out.size() != 2) { - continue; - } - - out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end()); - out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end()); + if (file.is_open()) { + std::string line; + while (std::getline(file, line)) { + std::vector out; + std::stringstream stream(line); + std::string item; + while (std::getline(stream, item, '=')) { + out.push_back(std::move(item)); + } - if (out[0].compare(0, 1, "#") == 0) { - continue; - } + if (out.size() != 2) { + continue; + } - if (is_title_keys) { - auto rights_id_raw = Common::HexStringToArray<16>(out[0]); - u128 rights_id{}; - std::memcpy(rights_id.data(), rights_id_raw.data(), rights_id_raw.size()); - Key128 key = Common::HexStringToArray<16>(out[1]); - s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; - } else { - out[0] = Common::ToLower(out[0]); - if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) { - const auto& index = iter128->second; - const Key128 key = Common::HexStringToArray<16>(out[1]); - s128_keys[{index.type, index.field1, index.field2}] = key; - } else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) { - const auto& index = iter256->second; - const Key256 key = Common::HexStringToArray<32>(out[1]); - s256_keys[{index.type, index.field1, index.field2}] = key; - } else if (out[0].compare(0, 8, "keyblob_") == 0 && - out[0].compare(0, 9, "keyblob_k") != 0) { - if (!ValidCryptoRevisionString(out[0], 8, 2)) { - continue; - } + out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end()); + out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end()); - const auto index = std::strtoul(out[0].substr(8, 2).c_str(), nullptr, 16); - keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); - } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { - if (!ValidCryptoRevisionString(out[0], 18, 2)) { - continue; - } + if (out[0].compare(0, 1, "#") == 0) { + continue; + } - const auto index = std::strtoul(out[0].substr(18, 2).c_str(), nullptr, 16); - encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); - } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) { - eticket_extended_kek = Common::HexStringToArray<576>(out[1]); - } else if (out[0].compare(0, 19, "eticket_rsa_keypair") == 0) { - const auto key_data = Common::HexStringToArray<528>(out[1]); - std::memcpy(eticket_rsa_keypair.decryption_key.data(), key_data.data(), - eticket_rsa_keypair.decryption_key.size()); - std::memcpy(eticket_rsa_keypair.modulus.data(), key_data.data() + 0x100, - eticket_rsa_keypair.modulus.size()); - std::memcpy(eticket_rsa_keypair.exponent.data(), key_data.data() + 0x200, - eticket_rsa_keypair.exponent.size()); + if (is_title_keys) { + auto rights_id_raw = Common::HexStringToArray<16>(out[0]); + u128 rights_id{}; + std::memcpy(rights_id.data(), rights_id_raw.data(), rights_id_raw.size()); + Key128 key = Common::HexStringToArray<16>(out[1]); + s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; } else { - for (const auto& kv : KEYS_VARIABLE_LENGTH) { - if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) { + out[0] = Common::ToLower(out[0]); + if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) { + const auto& index = iter128->second; + const Key128 key = Common::HexStringToArray<16>(out[1]); + s128_keys[{index.type, index.field1, index.field2}] = key; + } else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) { + const auto& index = iter256->second; + const Key256 key = Common::HexStringToArray<32>(out[1]); + s256_keys[{index.type, index.field1, index.field2}] = key; + } else if (out[0].compare(0, 8, "keyblob_") == 0 && out[0].compare(0, 9, "keyblob_k") != 0) { + if (!ValidCryptoRevisionString(out[0], 8, 2)) { continue; } - if (out[0].compare(0, kv.second.size(), kv.second) == 0) { - const auto index = - std::strtoul(out[0].substr(kv.second.size(), 2).c_str(), nullptr, 16); - const auto sub = kv.first.second; - if (sub == 0) { - s128_keys[{kv.first.first, index, 0}] = - Common::HexStringToArray<16>(out[1]); - } else { - s128_keys[{kv.first.first, kv.first.second, index}] = - Common::HexStringToArray<16>(out[1]); - } - break; + const auto index = std::strtoul(out[0].substr(8, 2).c_str(), nullptr, 16); + keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); + } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { + if (!ValidCryptoRevisionString(out[0], 18, 2)) { + continue; + } + + const auto index = std::strtoul(out[0].substr(18, 2).c_str(), nullptr, 16); + encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); + } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) { + eticket_extended_kek = Common::HexStringToArray<576>(out[1]); + } else if (out[0].compare(0, 19, "eticket_rsa_keypair") == 0) { + const auto key_data = Common::HexStringToArray<528>(out[1]); + std::memcpy(eticket_rsa_keypair.decryption_key.data(), key_data.data(), eticket_rsa_keypair.decryption_key.size()); + std::memcpy(eticket_rsa_keypair.modulus.data(), key_data.data() + 0x100, eticket_rsa_keypair.modulus.size()); + std::memcpy(eticket_rsa_keypair.exponent.data(), key_data.data() + 0x200, eticket_rsa_keypair.exponent.size()); + } else { + for (const auto& kv : KEYS_VARIABLE_LENGTH) { + if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) { + continue; + } + if (out[0].compare(0, kv.second.size(), kv.second) == 0) { + const auto index = std::strtoul(out[0].substr(kv.second.size(), 2).c_str(), nullptr, 16); + const auto sub = kv.first.second; + if (sub == 0) { + s128_keys[{kv.first.first, index, 0}] = Common::HexStringToArray<16>(out[1]); + } else { + s128_keys[{kv.first.first, kv.first.second, index}] = Common::HexStringToArray<16>(out[1]); + } + break; + } } - } - static constexpr std::array kak_names = { - "key_area_key_application_", "key_area_key_ocean_", "key_area_key_system_"}; - for (size_t j = 0; j < kak_names.size(); ++j) { - const auto& match = kak_names[j]; - if (out[0].compare(0, std::strlen(match), match) == 0) { - const auto index = - std::strtoul(out[0].substr(std::strlen(match), 2).c_str(), nullptr, 16); - s128_keys[{S128KeyType::KeyArea, index, j}] = - Common::HexStringToArray<16>(out[1]); + constexpr std::array kak_names = { + "key_area_key_application_", "key_area_key_ocean_", "key_area_key_system_" + }; + for (size_t j = 0; j < kak_names.size(); ++j) { + const auto& match = kak_names[j]; + if (out[0].compare(0, std::strlen(match), match) == 0) { + const auto index = std::strtoul(out[0].substr(std::strlen(match), 2).c_str(), nullptr, 16); + s128_keys[{S128KeyType::KeyArea, index, j}] = Common::HexStringToArray<16>(out[1]); + } } } } @@ -789,13 +699,11 @@ bool KeyManager::BaseDeriveNecessary() const { } for (size_t i = 0; i < CURRENT_CRYPTO_REVISION; ++i) { - if (check_key_existence(S128KeyType::Master, i) || - check_key_existence(S128KeyType::KeyArea, i, - static_cast(KeyAreaKeyType::Application)) || - check_key_existence(S128KeyType::KeyArea, i, static_cast(KeyAreaKeyType::Ocean)) || - check_key_existence(S128KeyType::KeyArea, i, - static_cast(KeyAreaKeyType::System)) || - check_key_existence(S128KeyType::Titlekek, i)) + if (check_key_existence(S128KeyType::Master, i) + || check_key_existence(S128KeyType::KeyArea, i, u64(KeyAreaKeyType::Application)) + || check_key_existence(S128KeyType::KeyArea, i, u64(KeyAreaKeyType::Ocean)) + || check_key_existence(S128KeyType::KeyArea, i, u64(KeyAreaKeyType::System)) + || check_key_existence(S128KeyType::Titlekek, i)) return true; } @@ -828,10 +736,10 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const { Key256 out{}; for (const auto& bis_type : {BISKeyType::Crypto, BISKeyType::Tweak}) { - if (HasKey(S128KeyType::BIS, partition_id, static_cast(bis_type))) { + if (HasKey(S128KeyType::BIS, partition_id, u64(bis_type))) { std::memcpy( - out.data() + sizeof(Key128) * static_cast(bis_type), - s128_keys.at({S128KeyType::BIS, partition_id, static_cast(bis_type)}).data(), + out.data() + sizeof(Key128) * u64(bis_type), + s128_keys.at({S128KeyType::BIS, partition_id, u64(bis_type)}).data(), sizeof(Key128)); } } @@ -840,8 +748,7 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const { } template -void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, - const std::array& key) { +void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, const std::array& key) { const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); std::string filename = "title.keys_autogenerated"; @@ -889,11 +796,9 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { category = KeyCategory::Console; } - const auto iter2 = std::find_if( - s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) { - return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == - std::tie(id, field1, field2); - }); + const auto iter2 = std::find_if(s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) { + return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == std::tie(id, field1, field2); + }); if (iter2 != s128_file_id.end()) { WriteKeyToFile(category, iter2->first, key); } @@ -918,7 +823,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { WriteKeyToFile(category, fmt::format("keyblob_key_{:02X}", field1), key); } else if (id == S128KeyType::KeyblobMAC) { WriteKeyToFile(category, fmt::format("keyblob_mac_key_{:02X}", field1), key); - } else if (id == S128KeyType::Source && field1 == static_cast(SourceKeyType::Keyblob)) { + } else if (id == S128KeyType::Source && field1 == u64(SourceKeyType::Keyblob)) { WriteKeyToFile(category, fmt::format("keyblob_key_source_{:02X}", field2), key); } @@ -929,11 +834,10 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { if (s256_keys.find({id, field1, field2}) != s256_keys.end() || key == Key256{}) { return; } - const auto iter = std::find_if( - s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) { - return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == - std::tie(id, field1, field2); - }); + const auto iter = std::find_if(s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) { + return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == + std::tie(id, field1, field2); + }); if (iter != s256_file_id.end()) { WriteKeyToFile(KeyCategory::Standard, iter->first, key); } @@ -988,18 +892,17 @@ void KeyManager::DeriveBase() { } const auto has_bis = [this](u64 id) { - return HasKey(S128KeyType::BIS, id, static_cast(BISKeyType::Crypto)) && - HasKey(S128KeyType::BIS, id, static_cast(BISKeyType::Tweak)); + return HasKey(S128KeyType::BIS, id, u64(BISKeyType::Crypto)) && HasKey(S128KeyType::BIS, id, u64(BISKeyType::Tweak)); }; const auto copy_bis = [this](u64 id_from, u64 id_to) { SetKey(S128KeyType::BIS, - GetKey(S128KeyType::BIS, id_from, static_cast(BISKeyType::Crypto)), id_to, - static_cast(BISKeyType::Crypto)); + GetKey(S128KeyType::BIS, id_from, u64(BISKeyType::Crypto)), id_to, + u64(BISKeyType::Crypto)); SetKey(S128KeyType::BIS, - GetKey(S128KeyType::BIS, id_from, static_cast(BISKeyType::Tweak)), id_to, - static_cast(BISKeyType::Tweak)); + GetKey(S128KeyType::BIS, id_from, u64(BISKeyType::Tweak)), id_to, + u64(BISKeyType::Tweak)); }; if (has_bis(2) && !has_bis(3)) { @@ -1010,7 +913,7 @@ void KeyManager::DeriveBase() { std::bitset<32> revisions(0xFFFFFFFF); for (size_t i = 0; i < revisions.size(); ++i) { - if (!HasKey(S128KeyType::Source, static_cast(SourceKeyType::Keyblob), i) || + if (!HasKey(S128KeyType::Source, u64(SourceKeyType::Keyblob), i) || encrypted_keyblobs[i] == std::array{}) { revisions.reset(i); } @@ -1030,17 +933,17 @@ void KeyManager::DeriveBase() { // Derive keyblob key const auto key = DeriveKeyblobKey( - sbk, tsec, GetKey(S128KeyType::Source, static_cast(SourceKeyType::Keyblob), i)); + sbk, tsec, GetKey(S128KeyType::Source, u64(SourceKeyType::Keyblob), i)); SetKey(S128KeyType::Keyblob, key, i); // Derive keyblob MAC key - if (!HasKey(S128KeyType::Source, static_cast(SourceKeyType::KeyblobMAC))) { + if (!HasKey(S128KeyType::Source, u64(SourceKeyType::KeyblobMAC))) { continue; } const auto mac_key = DeriveKeyblobMACKey( - key, GetKey(S128KeyType::Source, static_cast(SourceKeyType::KeyblobMAC))); + key, GetKey(S128KeyType::Source, u64(SourceKeyType::KeyblobMAC))); SetKey(S128KeyType::KeyblobMAC, mac_key, i); Key128 cmac = CalculateCMAC(encrypted_keyblobs[i].data() + 0x10, 0xA0, mac_key); @@ -1060,10 +963,10 @@ void KeyManager::DeriveBase() { SetKey(S128KeyType::Package1, package1, i); // Derive master key - if (HasKey(S128KeyType::Source, static_cast(SourceKeyType::Master))) { + if (HasKey(S128KeyType::Source, u64(SourceKeyType::Master))) { SetKey(S128KeyType::Master, DeriveMasterKey(keyblobs[i], GetKey(S128KeyType::Source, - static_cast(SourceKeyType::Master))), + u64(SourceKeyType::Master))), i); } } @@ -1089,15 +992,15 @@ void KeyManager::DeriveBase() { } if (HasKey(S128KeyType::Master, 0) && - HasKey(S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration)) && - HasKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration)) && - HasKey(S128KeyType::Source, static_cast(SourceKeyType::HeaderKek)) && + HasKey(S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration)) && + HasKey(S128KeyType::Source, u64(SourceKeyType::AESKekGeneration)) && + HasKey(S128KeyType::Source, u64(SourceKeyType::HeaderKek)) && HasKey(S256KeyType::HeaderSource)) { const auto header_kek = GenerateKeyEncryptionKey( - GetKey(S128KeyType::Source, static_cast(SourceKeyType::HeaderKek)), + GetKey(S128KeyType::Source, u64(SourceKeyType::HeaderKek)), GetKey(S128KeyType::Master, 0), - GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration)), - GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKeyGeneration))); + GetKey(S128KeyType::Source, u64(SourceKeyType::AESKekGeneration)), + GetKey(S128KeyType::Source, u64(SourceKeyType::AESKeyGeneration))); SetKey(S128KeyType::HeaderKek, header_kek); AESCipher header_cipher(header_kek, Mode::ECB); @@ -1107,8 +1010,7 @@ void KeyManager::DeriveBase() { } } -void KeyManager::DeriveETicket(PartitionDataManager& data, - const FileSys::ContentProvider& provider) { +void KeyManager::DeriveETicket(PartitionDataManager& data, const FileSys::ContentProvider& provider) { // The emulator no longer derives the ETicket RSA Kek. // It is now required for the user to provide this key in their keys file. if (!HasKey(S128KeyType::ETicketRSAKek)) { @@ -1132,110 +1034,90 @@ void KeyManager::DeriveETicket(PartitionDataManager& data, } void KeyManager::PopulateTickets() { - if (ticket_databases_loaded) { - return; - } - ticket_databases_loaded = true; - - std::vector tickets; - - const auto system_save_e1_path = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e1"; - if (Common::FS::Exists(system_save_e1_path)) { - const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read, - Common::FS::FileType::BinaryFile}; - const auto blob1 = GetTicketblob(save_e1); - tickets.insert(tickets.end(), blob1.begin(), blob1.end()); - } + if (!ticket_databases_loaded) { + ticket_databases_loaded = true; + + std::vector tickets; + const auto system_save_e1_path = + Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e1"; + if (Common::FS::Exists(system_save_e1_path)) { + const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read, Common::FS::FileType::BinaryFile}; + const auto blob1 = GetTicketblob(save_e1); + tickets.insert(tickets.end(), blob1.begin(), blob1.end()); + } - const auto system_save_e2_path = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e2"; - if (Common::FS::Exists(system_save_e2_path)) { - const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read, - Common::FS::FileType::BinaryFile}; - const auto blob2 = GetTicketblob(save_e2); - tickets.insert(tickets.end(), blob2.begin(), blob2.end()); - } + const auto system_save_e2_path = + Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e2"; + if (Common::FS::Exists(system_save_e2_path)) { + const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read, Common::FS::FileType::BinaryFile}; + const auto blob2 = GetTicketblob(save_e2); + tickets.insert(tickets.end(), blob2.begin(), blob2.end()); + } - for (const auto& ticket : tickets) { - AddTicket(ticket); + for (const auto& ticket : tickets) { + AddTicket(ticket); + } } } void KeyManager::SynthesizeTickets() { for (const auto& key : s128_keys) { - if (key.first.type != S128KeyType::Titlekey) { - continue; + if (key.first.type == S128KeyType::Titlekey) { + u128 rights_id{key.first.field1, key.first.field2}; + Key128 rights_id_2; + std::memcpy(rights_id_2.data(), rights_id.data(), rights_id_2.size()); + const auto ticket = Ticket::SynthesizeCommon(key.second, rights_id_2); + common_tickets.insert_or_assign(rights_id, ticket); } - u128 rights_id{key.first.field1, key.first.field2}; - Key128 rights_id_2; - std::memcpy(rights_id_2.data(), rights_id.data(), rights_id_2.size()); - const auto ticket = Ticket::SynthesizeCommon(key.second, rights_id_2); - common_tickets.insert_or_assign(rights_id, ticket); } } void KeyManager::SetKeyWrapped(S128KeyType id, Key128 key, u64 field1, u64 field2) { - if (key == Key128{}) { - return; + if (key != Key128{}) { + SetKey(id, key, field1, field2); } - SetKey(id, key, field1, field2); } void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field2) { - if (key == Key256{}) { - return; + if (key != Key256{}) { + SetKey(id, key, field1, field2); } - - SetKey(id, key, field1, field2); } void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { - if (!BaseDeriveNecessary()) { - return; - } - - if (!data.HasBoot0()) { - return; - } - - for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) { - if (encrypted_keyblobs[i] != std::array{}) { - continue; + if (BaseDeriveNecessary() && data.HasBoot0()) { + for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) { + if (encrypted_keyblobs[i] == std::array{}) { + encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); + WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), encrypted_keyblobs[i]); + } } - encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); - WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), - encrypted_keyblobs[i]); - } - - if (data.HasFuses()) { - SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); - } - DeriveBase(); - - Key128 latest_master{}; - for (s8 i = 0x1F; i >= 0; --i) { - if (GetKey(S128KeyType::Master, static_cast(i)) != Key128{}) { - latest_master = GetKey(S128KeyType::Master, static_cast(i)); - break; + if (data.HasFuses()) { + SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); } - } + DeriveBase(); - DeriveBase(); - - if (!data.HasPackage2()) - return; + Key128 latest_master{}; + for (s8 i = 0x1F; i >= 0; --i) { + if (GetKey(S128KeyType::Master, static_cast(i)) != Key128{}) { + latest_master = GetKey(S128KeyType::Master, static_cast(i)); + break; + } + } + DeriveBase(); - std::array package2_keys{}; - for (size_t i = 0; i < package2_keys.size(); ++i) { - if (HasKey(S128KeyType::Package2, i)) { - package2_keys[i] = GetKey(S128KeyType::Package2, i); + if (data.HasPackage2()) { + std::array package2_keys{}; + for (size_t i = 0; i < package2_keys.size(); ++i) { + if (HasKey(S128KeyType::Package2, i)) { + package2_keys[i] = GetKey(S128KeyType::Package2, i); + } + } + data.DecryptPackage2(package2_keys, Package2Type::NormalMain); + DeriveBase(); } } - data.DecryptPackage2(package2_keys, Package2Type::NormalMain); - - DeriveBase(); } const std::map& KeyManager::GetCommonTickets() const { @@ -1263,8 +1145,8 @@ bool KeyManager::AddTicket(const Ticket& ticket) { if (HasKey(S128KeyType::Titlekey, rights_id[1], rights_id[0])) { LOG_DEBUG(Crypto, - "Skipping parsing title key from ticket for known rights ID {:016X}{:016X}.", - rights_id[1], rights_id[0]); + "Skipping parsing title key from ticket for known rights ID {:016X}{:016X}.", + rights_id[1], rights_id[0]); return true; } diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 7ef8375690..4a892a27ed 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -336,8 +336,7 @@ Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, K Key128 DeriveKeyblobKey(const Key128& sbk, const Key128& tsec, Key128 source); Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source); Key128 DeriveMasterKey(const std::array& keyblob, const Key128& master_source); -std::array DecryptKeyblob(const std::array& encrypted_keyblob, - const Key128& key); +std::array DecryptKeyblob(const std::array& encrypted_keyblob, const Key128& key); std::optional DeriveSDSeed(); Loader::ResultStatus DeriveSDKeys(std::array& sd_keys, KeyManager& keys); diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp index e94eb2c882..144ae8e141 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp @@ -242,11 +242,8 @@ size_t AesCtrCounterExtendedStorage::Read(u8* buffer, size_t size, size_t offset return size; } -void SoftwareDecryptor::Decrypt(u8* buf, size_t buf_size, - const std::array& key, - const std::array& iv) { - Core::Crypto::AESCipher cipher( - key, Core::Crypto::Mode::CTR); +void SoftwareDecryptor::Decrypt(u8* buf, size_t buf_size, const std::array& key, const std::array& iv) { + Core::Crypto::AESCipher cipher(key, Core::Crypto::Mode::CTR); cipher.SetIV(iv); cipher.Transcode(buf, buf_size, buf, Core::Crypto::Op::Decrypt); } diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index 4fc2e7ced3..024f06faba 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp @@ -140,7 +140,7 @@ void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address } bool ProgramMetadata::Is64BitProgram() const { - return npdm_header.has_64_bit_instructions.As(); + return npdm_header.has_64_bit_instructions; } ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const { diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index ebc66932ab..dff5df47f4 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp @@ -71,78 +71,58 @@ Hidbus::~Hidbus() { void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) { if (is_hidbus_enabled) { for (std::size_t i = 0; i < devices.size(); ++i) { - if (!devices[i].is_device_initialized) { - continue; + if (devices[i].is_device_initialized) { + auto& device = devices[i].device; + device->OnUpdate(); + auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index]; + cur_entry.is_polling_mode = device->IsPollingMode(); + cur_entry.polling_mode = device->GetPollingMode(); + cur_entry.is_enabled = device->IsEnabled(); + u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer(); + std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status, sizeof(HidbusStatusManagerEntry)); } - auto& device = devices[i].device; - device->OnUpdate(); - auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index]; - cur_entry.is_polling_mode = device->IsPollingMode(); - cur_entry.polling_mode = device->GetPollingMode(); - cur_entry.is_enabled = device->IsEnabled(); - - u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer(); - std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status, - sizeof(HidbusStatusManagerEntry)); } } } std::optional Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const { - for (std::size_t i = 0; i < devices.size(); ++i) { - const auto& device_handle = devices[i].handle; - if (handle.abstracted_pad_id == device_handle.abstracted_pad_id && - handle.internal_index == device_handle.internal_index && - handle.player_number == device_handle.player_number && - handle.bus_type_id == device_handle.bus_type_id && - handle.is_valid == device_handle.is_valid) { - return i; - } - } - return std::nullopt; + auto const it = std::ranges::find_if(devices, [&handle](auto const& e) { + return handle.abstracted_pad_id == e.handle.abstracted_pad_id + && handle.internal_index == e.handle.internal_index + && handle.player_number == e.handle.player_number + && handle.bus_type_id == e.handle.bus_type_id + && handle.is_valid == e.handle.is_valid; + }); + return it != devices.end() + ? std::optional{std::distance(devices.begin(), it)} + : std::nullopt; } -Result Hidbus::GetBusHandle(Out out_is_valid, Out out_bus_handle, - Core::HID::NpadIdType npad_id, BusType bus_type, - AppletResourceUserId aruid) { - LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id, - bus_type, aruid.pid); - - bool is_handle_found = 0; - std::size_t handle_index = 0; - - for (std::size_t i = 0; i < devices.size(); i++) { - const auto& handle = devices[i].handle; - if (!handle.is_valid) { - continue; - } - if (handle.player_number.As() == npad_id && - handle.bus_type_id == static_cast(bus_type)) { - is_handle_found = true; - handle_index = i; - break; - } - } - +Result Hidbus::GetBusHandle(Out out_is_valid, Out out_bus_handle, Core::HID::NpadIdType npad_id, BusType bus_type, AppletResourceUserId aruid) { + LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id, bus_type, aruid.pid); + *out_is_valid = false; + *out_bus_handle = devices[0].handle; //TODO: does it give 0th? + if (auto const it = std::ranges::find_if(devices, [npad_id, bus_type](auto const& e) { + return e.handle.is_valid && e.handle.player_number == u64(npad_id) && e.handle.bus_type_id == u8(bus_type); + }); it != devices.end()) { + *out_bus_handle = devices[std::distance(devices.begin(), it)].handle; + *out_is_valid = true; // Handle not found. Create a new one - if (!is_handle_found) { - for (std::size_t i = 0; i < devices.size(); i++) { - if (devices[i].handle.is_valid) { - continue; - } - devices[i].handle.raw = 0; - devices[i].handle.abstracted_pad_id.Assign(i); - devices[i].handle.internal_index.Assign(i); - devices[i].handle.player_number.Assign(static_cast(npad_id)); - devices[i].handle.bus_type_id.Assign(static_cast(bus_type)); - devices[i].handle.is_valid.Assign(true); - handle_index = i; - break; - } + } else if (auto const free_it = std::ranges::find_if(devices, [](auto const& e) { + return !e.handle.is_valid; + }); free_it != devices.end()) { + auto const i = std::distance(devices.begin(), free_it); + devices[i].handle.raw = 0; + devices[i].handle.abstracted_pad_id.Assign(i); + devices[i].handle.internal_index.Assign(i); + devices[i].handle.player_number.Assign(u8(npad_id)); + devices[i].handle.bus_type_id.Assign(u8(bus_type)); + devices[i].handle.is_valid.Assign(true); + *out_bus_handle = devices[i].handle; + *out_is_valid = true; + } else { + LOG_ERROR(Service_HID, "no free or matching handle found"); } - - *out_is_valid = true; - *out_bus_handle = devices[handle_index].handle; R_SUCCEED(); } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 1238a21f85..dad3ab048c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -127,7 +127,7 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { vm.va_range_end = params.va_range_end; } - const u64 max_big_page_bits = Common::Log2Ceil64(vm.va_range_end); + const u64 max_big_page_bits = Common::Log2Ceil(vm.va_range_end); const auto start_pages{static_cast(vm.va_range_start >> VM::PAGE_SIZE_BITS)}; const auto end_pages{static_cast(vm.va_range_split >> VM::PAGE_SIZE_BITS)}; diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h index d7502d2b83..eaeedf85af 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h @@ -85,8 +85,8 @@ public: /// @brief Code emitter: Calls the function template + requires std::is_pointer_v && std::is_function_v> void CallFunction(F fn) { - static_assert(std::is_pointer_v && std::is_function_v>, "Supplied type must be a pointer to a function"); ::Common::X64::CallFarFunction(*this, fn); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp index 4df09e4797..1165abb0e4 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -5076,9 +5076,8 @@ void EmitX64::EmitVectorSignedSaturatedNeg64(EmitContext& ctx, IR::Inst* inst) { # pragma clang diagnostic ignored "-Wunused-lambda-capture" #endif template> + requires std::is_signed_v static bool VectorSignedSaturatedShiftLeft(VectorArray& dst, const VectorArray& data, const VectorArray& shift_values) { - static_assert(std::is_signed_v, "T must be signed."); - bool qc_flag = false; constexpr size_t bit_size_minus_one = mcl::bitsizeof - 1; @@ -5134,9 +5133,9 @@ void EmitX64::EmitVectorSignedSaturatedShiftLeft64(EmitContext& ctx, IR::Inst* i } template + requires std::is_signed_v static bool VectorSignedSaturatedShiftLeftUnsigned(VectorArray& dst, const VectorArray& data, u8 shift_amount) { using U = std::make_unsigned_t; - static_assert(std::is_signed_v, "T must be signed."); bool qc_flag = false; for (size_t i = 0; i < dst.size(); i++) { auto const element = data[i]; @@ -6030,17 +6029,15 @@ void EmitX64::EmitVectorUnsignedRecipSqrtEstimate(EmitContext& ctx, IR::Inst* in // Simple generic case for 8, 16, and 32-bit values. 64-bit values // will need to be special-cased as we can't simply use a larger integral size. template> + requires std::is_signed_v static bool EmitVectorUnsignedSaturatedAccumulateSigned(VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { - static_assert(std::is_signed_v, "T must be signed."); static_assert(mcl::bitsizeof < 64, "T must be less than 64 bits in size."); - bool qc_flag = false; - for (size_t i = 0; i < result.size(); i++) { // We treat rhs' members as unsigned, so cast to unsigned before signed to inhibit sign-extension. // We use the unsigned equivalent of T, as we want zero-extension to occur, rather than a plain move. const s64 x = s64{lhs[i]}; - const s64 y = static_cast(static_cast>(rhs[i])); + const s64 y = s64(std::make_unsigned_t(rhs[i])); const s64 sum = x + y; if (sum > (std::numeric_limits::max)()) { @@ -6050,10 +6047,9 @@ static bool EmitVectorUnsignedSaturatedAccumulateSigned(VectorArray& result, result[i] = (std::numeric_limits::min)(); qc_flag = true; } else { - result[i] = static_cast(sum); + result[i] = U(sum); } } - return qc_flag; } @@ -6134,29 +6130,23 @@ void EmitX64::EmitVectorUnsignedSaturatedNarrow64(EmitContext& ctx, IR::Inst* in } template> + requires std::is_unsigned_v static bool VectorUnsignedSaturatedShiftLeft(VectorArray& dst, const VectorArray& data, const VectorArray& shift_values) { - static_assert(std::is_unsigned_v, "T must be an unsigned type."); - bool qc_flag = false; - constexpr size_t bit_size = mcl::bitsizeof; - constexpr S negative_bit_size = -static_cast(bit_size); - + constexpr S negative_bit_size = -S(bit_size); for (size_t i = 0; i < dst.size(); i++) { const T element = data[i]; - const S shift = std::clamp(static_cast(mcl::bit::sign_extend<8>(static_cast(shift_values[i] & 0xFF))), - negative_bit_size, (std::numeric_limits::max)()); - + const S shift = std::clamp(S(mcl::bit::sign_extend<8>(T(shift_values[i] & 0xFF))), negative_bit_size, (std::numeric_limits::max)()); if (element == 0 || shift <= negative_bit_size) { dst[i] = 0; } else if (shift < 0) { - dst[i] = static_cast(element >> -shift); - } else if (shift >= static_cast(bit_size)) { + dst[i] = T(element >> -shift); + } else if (shift >= S(bit_size)) { dst[i] = (std::numeric_limits::max)(); qc_flag = true; } else { const T shifted = element << shift; - if ((shifted >> shift) != element) { dst[i] = (std::numeric_limits::max)(); qc_flag = true; diff --git a/src/dynarmic/src/dynarmic/common/safe_ops.h b/src/dynarmic/src/dynarmic/common/safe_ops.h index f5559336e0..261272bb58 100644 --- a/src/dynarmic/src/dynarmic/common/safe_ops.h +++ b/src/dynarmic/src/dynarmic/common/safe_ops.h @@ -28,18 +28,11 @@ T ArithmeticShiftRight(T value, int shift_amount); template T LogicalShiftLeft(T value, int shift_amount) { - static_assert(std::is_integral_v); - - if (shift_amount >= static_cast(mcl::bitsizeof)) { + if (shift_amount >= int(mcl::bitsizeof)) return 0; - } - - if (shift_amount < 0) { - return LogicalShiftRight(value, -shift_amount); - } - - auto unsigned_value = static_cast>(value); - return static_cast(unsigned_value << shift_amount); + return shift_amount < 0 + ? LogicalShiftRight(value, -shift_amount) + : T(std::make_unsigned_t(value) << shift_amount); } template<> @@ -49,18 +42,11 @@ inline u128 LogicalShiftLeft(u128 value, int shift_amount) { template T LogicalShiftRight(T value, int shift_amount) { - static_assert(std::is_integral_v); - - if (shift_amount >= static_cast(mcl::bitsizeof)) { + if (shift_amount >= int(mcl::bitsizeof)) return 0; - } - - if (shift_amount < 0) { - return LogicalShiftLeft(value, -shift_amount); - } - - auto unsigned_value = static_cast>(value); - return static_cast(unsigned_value >> shift_amount); + return shift_amount < 0 + ? LogicalShiftLeft(value, -shift_amount) + : T(std::make_unsigned_t(value) >> shift_amount); } template<> @@ -75,34 +61,20 @@ T LogicalShiftRightDouble(T top, T bottom, int shift_amount) { template T ArithmeticShiftLeft(T value, int shift_amount) { - static_assert(std::is_integral_v); - - if (shift_amount >= static_cast(mcl::bitsizeof)) { + if (shift_amount >= int(mcl::bitsizeof)) return 0; - } - - if (shift_amount < 0) { - return ArithmeticShiftRight(value, -shift_amount); - } - - auto unsigned_value = static_cast>(value); - return static_cast(unsigned_value << shift_amount); + return shift_amount < 0 + ? ArithmeticShiftRight(value, -shift_amount) + : T(std::make_unsigned_t(value) << shift_amount); } template T ArithmeticShiftRight(T value, int shift_amount) { - static_assert(std::is_integral_v); - - if (shift_amount >= static_cast(mcl::bitsizeof)) { - return mcl::bit::most_significant_bit(value) ? ~static_cast(0) : 0; - } - - if (shift_amount < 0) { - return ArithmeticShiftLeft(value, -shift_amount); - } - - auto signed_value = static_cast>(value); - return static_cast(signed_value >> shift_amount); + if (shift_amount >= int(mcl::bitsizeof)) + return mcl::bit::most_significant_bit(value) ? ~T(0) : 0; + return shift_amount < 0 + ? ArithmeticShiftLeft(value, -shift_amount) + : T(std::make_signed_t(value) >> shift_amount); } template @@ -112,7 +84,7 @@ T ArithmeticShiftRightDouble(T top, T bottom, int shift_amount) { template T Negate(T value) { - return static_cast(~static_cast(value) + 1); + return T(~std::uintmax_t(value) + 1); } } // namespace Dynarmic::Safe diff --git a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h index 566743c767..05b067bdd8 100644 --- a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h +++ b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -47,8 +50,8 @@ public: /// the exclusive state for processors if their exclusive region(s) /// contain [address, address+size). template + requires std::is_trivially_copyable_v bool DoExclusiveOperation(size_t processor_id, VAddr address, Function op) { - static_assert(std::is_trivially_copyable_v); if (!CheckAndClear(processor_id, address)) { return false; } diff --git a/src/dynarmic/tests/rand_int.h b/src/dynarmic/tests/rand_int.h index 3997a43130..1c62d94705 100644 --- a/src/dynarmic/tests/rand_int.h +++ b/src/dynarmic/tests/rand_int.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD @@ -17,11 +20,9 @@ inline std::mt19937 g_rand_int_generator = [] { } // namespace detail template + requires std::is_integral_v + && (!std::is_same_v && !std::is_same_v) T RandInt(T min, T max) { - static_assert(std::is_integral_v, "T must be an integral type."); - static_assert(!std::is_same_v && !std::is_same_v, - "Using char with uniform_int_distribution is undefined behavior."); - std::uniform_int_distribution rand(min, max); return rand(detail::g_rand_int_generator); } diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 3ebb9133dd..d9300ddc37 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -1661,17 +1661,17 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { const auto type = is_configuring.load() && use_temporary_value ? tmp_npad_type.load() : npad_type.load(); switch (type) { - case NpadStyleIndex::Fullkey: return supported_style_tag.fullkey.As(); - case NpadStyleIndex::Handheld: return supported_style_tag.handheld.As(); - case NpadStyleIndex::JoyconDual: return supported_style_tag.joycon_dual.As(); - case NpadStyleIndex::JoyconLeft: return supported_style_tag.joycon_left.As(); - case NpadStyleIndex::JoyconRight: return supported_style_tag.joycon_right.As(); - case NpadStyleIndex::GameCube: return supported_style_tag.gamecube.As(); - case NpadStyleIndex::Pokeball: return supported_style_tag.palma.As(); - case NpadStyleIndex::NES: return supported_style_tag.lark.As(); - case NpadStyleIndex::SNES: return supported_style_tag.lucia.As(); - case NpadStyleIndex::N64: return supported_style_tag.lagoon.As(); - case NpadStyleIndex::SegaGenesis: return supported_style_tag.lager.As(); + case NpadStyleIndex::Fullkey: return supported_style_tag.fullkey; + case NpadStyleIndex::Handheld: return supported_style_tag.handheld; + case NpadStyleIndex::JoyconDual: return supported_style_tag.joycon_dual; + case NpadStyleIndex::JoyconLeft: return supported_style_tag.joycon_left; + case NpadStyleIndex::JoyconRight: return supported_style_tag.joycon_right; + case NpadStyleIndex::GameCube: return supported_style_tag.gamecube; + case NpadStyleIndex::Pokeball: return supported_style_tag.palma; + case NpadStyleIndex::NES: return supported_style_tag.lark; + case NpadStyleIndex::SNES: return supported_style_tag.lucia; + case NpadStyleIndex::N64: return supported_style_tag.lagoon; + case NpadStyleIndex::SegaGenesis: return supported_style_tag.lager; default: return false; } } diff --git a/src/hid_core/hidbus/ringcon.cpp b/src/hid_core/hidbus/ringcon.cpp index b942cad480..74b4d7189b 100644 --- a/src/hid_core/hidbus/ringcon.cpp +++ b/src/hid_core/hidbus/ringcon.cpp @@ -284,9 +284,9 @@ u8 RingController::GetCrcValue(const std::vector& data) const { } template + requires std::is_trivially_copyable_v u64 RingController::GetData(const T& reply, std::span out_data) const { - static_assert(std::is_trivially_copyable_v); - const auto data_size = static_cast((std::min)(sizeof(reply), out_data.size())); + const auto data_size = u64((std::min)(sizeof(reply), out_data.size())); std::memcpy(out_data.data(), &reply, data_size); return data_size; } diff --git a/src/hid_core/hidbus/ringcon.h b/src/hid_core/hidbus/ringcon.h index a48eeed459..b38a67bc3e 100644 --- a/src/hid_core/hidbus/ringcon.h +++ b/src/hid_core/hidbus/ringcon.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -221,6 +224,7 @@ private: // Converts structs to an u8 vector equivalent template + requires std::is_trivially_copyable_v u64 GetData(const T& reply, std::span out_data) const; RingConCommands command{RingConCommands::Error}; diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp index 54055751a2..de84a5ec28 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp @@ -66,8 +66,7 @@ Result NpadAbstractSixAxisHandler::UpdateSixAxisState() { continue; } auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; - UpdateSixaxisInternalState(npad_entry, data->aruid, - data->flag.enable_six_axis_sensor.As()); + UpdateSixaxisInternalState(npad_entry, data->aruid, data->flag.enable_six_axis_sensor); } return ResultSuccess; } @@ -79,8 +78,7 @@ Result NpadAbstractSixAxisHandler::UpdateSixAxisState(u64 aruid) { return ResultSuccess; } auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; - UpdateSixaxisInternalState(npad_entry, data->aruid, - data->flag.enable_six_axis_sensor.As()); + UpdateSixaxisInternalState(npad_entry, data->aruid, data->flag.enable_six_axis_sensor); return ResultSuccess; } @@ -91,8 +89,7 @@ Result NpadAbstractSixAxisHandler::UpdateSixAxisState2(u64 aruid) { return ResultSuccess; } auto& npad_internal_state = aruid_data->shared_memory_format->npad.npad_entry[npad_index]; - UpdateSixaxisInternalState(npad_internal_state, aruid, - aruid_data->flag.enable_six_axis_sensor.As()); + UpdateSixaxisInternalState(npad_internal_state, aruid, aruid_data->flag.enable_six_axis_sensor); return ResultSuccess; } diff --git a/src/hid_core/resources/npad/npad_data.cpp b/src/hid_core/resources/npad/npad_data.cpp index a490fe8a54..4b0bf44488 100644 --- a/src/hid_core/resources/npad/npad_data.cpp +++ b/src/hid_core/resources/npad/npad_data.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -24,7 +24,7 @@ void NPadData::SetNpadAnalogStickUseCenterClamp(bool is_enabled) { } bool NPadData::GetNpadAnalogStickUseCenterClamp() const { - return status.use_center_clamp.As(); + return status.use_center_clamp; } void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { @@ -32,7 +32,7 @@ void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { } bool NPadData::GetNpadSystemExtState() const { - return status.system_ext_state.As(); + return status.system_ext_state; } Result NPadData::SetSupportedNpadIdType(std::span list) { @@ -154,27 +154,27 @@ bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) Core::HID::NpadStyleTag style = {supported_npad_style_set}; switch (style_index) { case Core::HID::NpadStyleIndex::Fullkey: - return style.fullkey.As(); + return style.fullkey; case Core::HID::NpadStyleIndex::Handheld: - return style.handheld.As(); + return style.handheld; case Core::HID::NpadStyleIndex::JoyconDual: - return style.joycon_dual.As(); + return style.joycon_dual; case Core::HID::NpadStyleIndex::JoyconLeft: - return style.joycon_left.As(); + return style.joycon_left; case Core::HID::NpadStyleIndex::JoyconRight: - return style.joycon_right.As(); + return style.joycon_right; case Core::HID::NpadStyleIndex::GameCube: - return style.gamecube.As(); + return style.gamecube; case Core::HID::NpadStyleIndex::Pokeball: - return style.palma.As(); + return style.palma; case Core::HID::NpadStyleIndex::NES: - return style.lark.As(); + return style.lark; case Core::HID::NpadStyleIndex::SNES: - return style.lucia.As(); + return style.lucia; case Core::HID::NpadStyleIndex::N64: - return style.lagoon.As(); + return style.lagoon; case Core::HID::NpadStyleIndex::SegaGenesis: - return style.lager.As(); + return style.lager; default: return false; } @@ -185,7 +185,7 @@ void NPadData::SetLrAssignmentMode(bool is_enabled) { } bool NPadData::GetLrAssignmentMode() const { - return status.lr_assignment_mode.As(); + return status.lr_assignment_mode; } void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { @@ -193,7 +193,7 @@ void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { } bool NPadData::GetAssigningSingleOnSlSrPress() const { - return status.assigning_single_on_sl_sr_press.As(); + return status.assigning_single_on_sl_sr_press; } void NPadData::SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id) { diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp index d340f186b3..b5d17ad55e 100644 --- a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp @@ -548,8 +548,7 @@ void TouchResource::OnTouchUpdate(s64 timestamp) { } auto& touch_shared = applet_data->shared_memory_format->touch_screen; - StorePreviousTouchState(previous_touch_state, data.finger_map, current_touch_state, - applet_data->flag.enable_touchscreen.As()); + StorePreviousTouchState(previous_touch_state, data.finger_map, current_touch_state, applet_data->flag.enable_touchscreen); touch_shared.touch_screen_lifo.WriteNextEntry(current_touch_state); } } diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 06d405c2f5..154cb88e48 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -527,7 +527,7 @@ private: template size_t ObtainBuffer(size_t num_needed) { - const size_t log_2 = std::max(11U, Common::Log2Ceil64(num_needed)); + const size_t log_2 = std::max(11U, Common::Log2Ceil(num_needed)); if constexpr (is_resolve) { if (resolve_table[log_2] != 0) { return resolve_table[log_2] - 1; diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index e3ec62c9fd..d83c2285a1 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp @@ -174,7 +174,7 @@ StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage us std::optional StagingBufferPool::TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred) { - StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)]; + StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)]; const auto is_free = [this](const StagingBuffer& entry) { return !entry.deferred && scheduler.IsFree(entry.tick); @@ -195,14 +195,13 @@ std::optional StagingBufferPool::TryGetReservedBuffer(size_t s return it->Ref(); } -StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, - bool deferred) { - const u32 log2 = Common::Log2Ceil64(size); +StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred) { + auto const log2_size = Common::Log2Ceil(u32(size)); VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = 1ULL << log2, + .size = 1ULL << log2_size, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, @@ -219,11 +218,11 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str()); } const std::span mapped_span = buffer.Mapped(); - StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{ + StagingBuffer& entry = GetCache(usage)[log2_size].entries.emplace_back(StagingBuffer{ .buffer = std::move(buffer), .mapped_span = mapped_span, .usage = usage, - .log2_level = log2, + .log2_level = log2_size, .index = unique_ids++, .tick = deferred ? (std::numeric_limits::max)() : scheduler.CurrentTick(), .deferred = deferred, diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index 183b6b903b..95c6d72f89 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -219,16 +219,13 @@ void SerializePipeline(std::span key, std::span -void SerializePipeline(const Key& key, const Envs& envs, const std::filesystem::path& filename, - u32 cache_version) { - static_assert(std::is_trivially_copyable_v); - static_assert(std::has_unique_object_representations_v); - SerializePipeline(std::span(reinterpret_cast(&key), sizeof(key)), - std::span(envs.data(), envs.size()), filename, cache_version); + requires std::is_trivially_copyable_v + && std::has_unique_object_representations_v +void SerializePipeline(const Key& key, const Envs& envs, const std::filesystem::path& filename, u32 cache_version) { + SerializePipeline(std::span(reinterpret_cast(&key), sizeof(key)), std::span(envs.data(), envs.size()), filename, cache_version); } -void LoadPipelines( - std::stop_token stop_loading, const std::filesystem::path& filename, u32 expected_cache_version, +void LoadPipelines(std::stop_token stop_loading, const std::filesystem::path& filename, u32 expected_cache_version, Common::UniqueFunction load_compute, Common::UniqueFunction> load_graphics); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 87870893c5..64ee105f82 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -1357,10 +1357,9 @@ public: } template - void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags, - const T& data) const noexcept { - static_assert(std::is_trivially_copyable_v, " is not trivially copyable"); - dld->vkCmdPushConstants(handle, layout, flags, 0, static_cast(sizeof(T)), &data); + requires std::is_trivially_copyable_v + void PushConstants(VkPipelineLayout layout, VkShaderStageFlags flags, const T& data) const noexcept { + dld->vkCmdPushConstants(handle, layout, flags, 0, u32(sizeof(T)), std::addressof(data)); } void SetViewport(u32 first, Span viewports) const noexcept { diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp index bc74f5da79..2801fbd321 100644 --- a/src/yuzu/main_window.cpp +++ b/src/yuzu/main_window.cpp @@ -4563,8 +4563,7 @@ static void AdjustLinkColor() { } void MainWindow::UpdateUITheme() { - const QString default_theme = QString::fromUtf8( - UISettings::themes[static_cast(UISettings::default_theme)].second); + const QString default_theme = QString::fromUtf8(UISettings::themes[size_t(UISettings::default_theme)].second); QString current_theme = QString::fromStdString(UISettings::values.theme); if (current_theme.isEmpty()) @@ -4575,8 +4574,7 @@ void MainWindow::UpdateUITheme() { AdjustLinkColor(); #else if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) { - QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme - : startup_icon_theme); + QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme : startup_icon_theme); QIcon::setThemeSearchPaths(QStringList(default_theme_paths)); if (isDarkMode()) { current_theme = QStringLiteral("default_dark");