diff options
Diffstat (limited to 'src')
31 files changed, 312 insertions, 281 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 26ae6c7fc..dfa38a357 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h | |||
| @@ -161,7 +161,7 @@ public: | |||
| 161 | } | 161 | } |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | // This constructor and assignment operator might be considered ambiguous: | 164 | /// This constructor and assignment operator might be considered ambiguous: |
| 165 | // Would they initialize the storage or just the bitfield? | 165 | // Would they initialize the storage or just the bitfield? |
| 166 | // Hence, delete them. Use the Assign method to set bitfield values! | 166 | // Hence, delete them. Use the Assign method to set bitfield values! |
| 167 | BitField(T val) = delete; | 167 | BitField(T val) = delete; |
diff --git a/src/common/concepts.h b/src/common/concepts.h index db5fb373d..54252e778 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h | |||
| @@ -23,10 +23,12 @@ concept IsSTLContainer = requires(T t) { | |||
| 23 | t.size(); | 23 | t.size(); |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | // Check if type T is derived from T2 | 26 | // TODO: Replace with std::derived_from when the <concepts> header |
| 27 | template <typename T, typename T2> | 27 | // is available on all supported platforms. |
| 28 | concept IsBaseOf = requires { | 28 | template <typename Derived, typename Base> |
| 29 | std::is_base_of_v<T, T2>; | 29 | concept DerivedFrom = requires { |
| 30 | std::is_base_of_v<Base, Derived>; | ||
| 31 | std::is_convertible_v<const volatile Derived*, const volatile Base*>; | ||
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| 32 | } // namespace Common | 34 | } // namespace Common |
diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp index c2f6cf0f6..74f52dd11 100644 --- a/src/common/hex_util.cpp +++ b/src/common/hex_util.cpp | |||
| @@ -3,21 +3,9 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/hex_util.h" | 5 | #include "common/hex_util.h" |
| 6 | #include "common/logging/log.h" | ||
| 7 | 6 | ||
| 8 | namespace Common { | 7 | namespace Common { |
| 9 | 8 | ||
| 10 | u8 ToHexNibble(char c1) { | ||
| 11 | if (c1 >= 65 && c1 <= 70) | ||
| 12 | return c1 - 55; | ||
| 13 | if (c1 >= 97 && c1 <= 102) | ||
| 14 | return c1 - 87; | ||
| 15 | if (c1 >= 48 && c1 <= 57) | ||
| 16 | return c1 - 48; | ||
| 17 | LOG_ERROR(Common, "Invalid hex digit: 0x{:02X}", c1); | ||
| 18 | return 0; | ||
| 19 | } | ||
| 20 | |||
| 21 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { | 9 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { |
| 22 | std::vector<u8> out(str.size() / 2); | 10 | std::vector<u8> out(str.size() / 2); |
| 23 | if (little_endian) { | 11 | if (little_endian) { |
| @@ -30,26 +18,4 @@ std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { | |||
| 30 | return out; | 18 | return out; |
| 31 | } | 19 | } |
| 32 | 20 | ||
| 33 | std::array<u8, 16> operator""_array16(const char* str, std::size_t len) { | ||
| 34 | if (len != 32) { | ||
| 35 | LOG_ERROR(Common, | ||
| 36 | "Attempting to parse string to array that is not of correct size (expected=32, " | ||
| 37 | "actual={}).", | ||
| 38 | len); | ||
| 39 | return {}; | ||
| 40 | } | ||
| 41 | return HexStringToArray<16>(str); | ||
| 42 | } | ||
| 43 | |||
| 44 | std::array<u8, 32> operator""_array32(const char* str, std::size_t len) { | ||
| 45 | if (len != 64) { | ||
| 46 | LOG_ERROR(Common, | ||
| 47 | "Attempting to parse string to array that is not of correct size (expected=64, " | ||
| 48 | "actual={}).", | ||
| 49 | len); | ||
| 50 | return {}; | ||
| 51 | } | ||
| 52 | return HexStringToArray<32>(str); | ||
| 53 | } | ||
| 54 | |||
| 55 | } // namespace Common | 21 | } // namespace Common |
diff --git a/src/common/hex_util.h b/src/common/hex_util.h index bb4736f96..a0a0e78a4 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h | |||
| @@ -14,19 +14,31 @@ | |||
| 14 | 14 | ||
| 15 | namespace Common { | 15 | namespace Common { |
| 16 | 16 | ||
| 17 | u8 ToHexNibble(char c1); | 17 | constexpr u8 ToHexNibble(char c) { |
| 18 | if (c >= 65 && c <= 70) { | ||
| 19 | return c - 55; | ||
| 20 | } | ||
| 21 | |||
| 22 | if (c >= 97 && c <= 102) { | ||
| 23 | return c - 87; | ||
| 24 | } | ||
| 25 | |||
| 26 | return c - 48; | ||
| 27 | } | ||
| 18 | 28 | ||
| 19 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); | 29 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); |
| 20 | 30 | ||
| 21 | template <std::size_t Size, bool le = false> | 31 | template <std::size_t Size, bool le = false> |
| 22 | std::array<u8, Size> HexStringToArray(std::string_view str) { | 32 | constexpr std::array<u8, Size> HexStringToArray(std::string_view str) { |
| 23 | std::array<u8, Size> out{}; | 33 | std::array<u8, Size> out{}; |
| 24 | if constexpr (le) { | 34 | if constexpr (le) { |
| 25 | for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) | 35 | for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) { |
| 26 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); | 36 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); |
| 37 | } | ||
| 27 | } else { | 38 | } else { |
| 28 | for (std::size_t i = 0; i < 2 * Size; i += 2) | 39 | for (std::size_t i = 0; i < 2 * Size; i += 2) { |
| 29 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); | 40 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); |
| 41 | } | ||
| 30 | } | 42 | } |
| 31 | return out; | 43 | return out; |
| 32 | } | 44 | } |
| @@ -48,7 +60,12 @@ std::string HexToString(const ContiguousContainer& data, bool upper = true) { | |||
| 48 | return out; | 60 | return out; |
| 49 | } | 61 | } |
| 50 | 62 | ||
| 51 | std::array<u8, 0x10> operator"" _array16(const char* str, std::size_t len); | 63 | constexpr std::array<u8, 16> AsArray(const char (&data)[17]) { |
| 52 | std::array<u8, 0x20> operator"" _array32(const char* str, std::size_t len); | 64 | return HexStringToArray<16>(data); |
| 65 | } | ||
| 66 | |||
| 67 | constexpr std::array<u8, 32> AsArray(const char (&data)[65]) { | ||
| 68 | return HexStringToArray<32>(data); | ||
| 69 | } | ||
| 53 | 70 | ||
| 54 | } // namespace Common | 71 | } // namespace Common |
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 04bc3128f..62cfde397 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -113,19 +113,19 @@ private: | |||
| 113 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | 113 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, |
| 114 | const char* function, std::string message) const { | 114 | const char* function, std::string message) const { |
| 115 | using std::chrono::duration_cast; | 115 | using std::chrono::duration_cast; |
| 116 | using std::chrono::microseconds; | ||
| 116 | using std::chrono::steady_clock; | 117 | using std::chrono::steady_clock; |
| 117 | 118 | ||
| 118 | Entry entry; | 119 | return { |
| 119 | entry.timestamp = | 120 | .timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin), |
| 120 | duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | 121 | .log_class = log_class, |
| 121 | entry.log_class = log_class; | 122 | .log_level = log_level, |
| 122 | entry.log_level = log_level; | 123 | .filename = filename, |
| 123 | entry.filename = filename; | 124 | .line_num = line_nr, |
| 124 | entry.line_num = line_nr; | 125 | .function = function, |
| 125 | entry.function = function; | 126 | .message = std::move(message), |
| 126 | entry.message = std::move(message); | 127 | .final_entry = false, |
| 127 | 128 | }; | |
| 128 | return entry; | ||
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | std::mutex writing_mutex; | 131 | std::mutex writing_mutex; |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index fc338c70d..e5d702568 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -21,19 +21,13 @@ class Filter; | |||
| 21 | */ | 21 | */ |
| 22 | struct Entry { | 22 | struct Entry { |
| 23 | std::chrono::microseconds timestamp; | 23 | std::chrono::microseconds timestamp; |
| 24 | Class log_class; | 24 | Class log_class{}; |
| 25 | Level log_level; | 25 | Level log_level{}; |
| 26 | const char* filename; | 26 | const char* filename = nullptr; |
| 27 | unsigned int line_num; | 27 | unsigned int line_num = 0; |
| 28 | std::string function; | 28 | std::string function; |
| 29 | std::string message; | 29 | std::string message; |
| 30 | bool final_entry = false; | 30 | bool final_entry = false; |
| 31 | |||
| 32 | Entry() = default; | ||
| 33 | Entry(Entry&& o) = default; | ||
| 34 | |||
| 35 | Entry& operator=(Entry&& o) = default; | ||
| 36 | Entry& operator=(const Entry& o) = default; | ||
| 37 | }; | 31 | }; |
| 38 | 32 | ||
| 39 | /** | 33 | /** |
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp index 4be76bb43..330996b24 100644 --- a/src/core/crypto/aes_util.cpp +++ b/src/core/crypto/aes_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | ||
| 5 | #include <mbedtls/cipher.h> | 6 | #include <mbedtls/cipher.h> |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| @@ -10,8 +11,10 @@ | |||
| 10 | 11 | ||
| 11 | namespace Core::Crypto { | 12 | namespace Core::Crypto { |
| 12 | namespace { | 13 | namespace { |
| 13 | std::vector<u8> CalculateNintendoTweak(std::size_t sector_id) { | 14 | using NintendoTweak = std::array<u8, 16>; |
| 14 | std::vector<u8> out(0x10); | 15 | |
| 16 | NintendoTweak CalculateNintendoTweak(std::size_t sector_id) { | ||
| 17 | NintendoTweak out{}; | ||
| 15 | for (std::size_t i = 0xF; i <= 0xF; --i) { | 18 | for (std::size_t i = 0xF; i <= 0xF; --i) { |
| 16 | out[i] = sector_id & 0xFF; | 19 | out[i] = sector_id & 0xFF; |
| 17 | sector_id >>= 8; | 20 | sector_id >>= 8; |
| @@ -64,13 +67,6 @@ AESCipher<Key, KeySize>::~AESCipher() { | |||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | template <typename Key, std::size_t KeySize> | 69 | template <typename Key, std::size_t KeySize> |
| 67 | void AESCipher<Key, KeySize>::SetIV(std::vector<u8> iv) { | ||
| 68 | ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, iv.data(), iv.size()) || | ||
| 69 | mbedtls_cipher_set_iv(&ctx->decryption_context, iv.data(), iv.size())) == 0, | ||
| 70 | "Failed to set IV on mbedtls ciphers."); | ||
| 71 | } | ||
| 72 | |||
| 73 | template <typename Key, std::size_t KeySize> | ||
| 74 | void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { | 70 | void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { |
| 75 | auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context; | 71 | auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context; |
| 76 | 72 | ||
| @@ -124,6 +120,13 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, std::size_t size, u8* | |||
| 124 | } | 120 | } |
| 125 | } | 121 | } |
| 126 | 122 | ||
| 123 | template <typename Key, std::size_t KeySize> | ||
| 124 | void AESCipher<Key, KeySize>::SetIVImpl(const u8* data, std::size_t size) { | ||
| 125 | ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data, size) || | ||
| 126 | mbedtls_cipher_set_iv(&ctx->decryption_context, data, size)) == 0, | ||
| 127 | "Failed to set IV on mbedtls ciphers."); | ||
| 128 | } | ||
| 129 | |||
| 127 | template class AESCipher<Key128>; | 130 | template class AESCipher<Key128>; |
| 128 | template class AESCipher<Key256>; | 131 | template class AESCipher<Key256>; |
| 129 | } // namespace Core::Crypto | 132 | } // namespace Core::Crypto |
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h index edc4ab910..e2a304186 100644 --- a/src/core/crypto/aes_util.h +++ b/src/core/crypto/aes_util.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <type_traits> | 8 | #include <type_traits> |
| 9 | #include <vector> | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 11 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/vfs.h" |
| 12 | 11 | ||
| @@ -32,10 +31,12 @@ class AESCipher { | |||
| 32 | 31 | ||
| 33 | public: | 32 | public: |
| 34 | AESCipher(Key key, Mode mode); | 33 | AESCipher(Key key, Mode mode); |
| 35 | |||
| 36 | ~AESCipher(); | 34 | ~AESCipher(); |
| 37 | 35 | ||
| 38 | void SetIV(std::vector<u8> iv); | 36 | template <typename ContiguousContainer> |
| 37 | void SetIV(const ContiguousContainer& container) { | ||
| 38 | SetIVImpl(std::data(container), std::size(container)); | ||
| 39 | } | ||
| 39 | 40 | ||
| 40 | template <typename Source, typename Dest> | 41 | template <typename Source, typename Dest> |
| 41 | void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const { | 42 | void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const { |
| @@ -59,6 +60,8 @@ public: | |||
| 59 | std::size_t sector_size, Op op); | 60 | std::size_t sector_size, Op op); |
| 60 | 61 | ||
| 61 | private: | 62 | private: |
| 63 | void SetIVImpl(const u8* data, std::size_t size); | ||
| 64 | |||
| 62 | std::unique_ptr<CipherContext> ctx; | 65 | std::unique_ptr<CipherContext> ctx; |
| 63 | }; | 66 | }; |
| 64 | } // namespace Core::Crypto | 67 | } // namespace Core::Crypto |
diff --git a/src/core/crypto/ctr_encryption_layer.cpp b/src/core/crypto/ctr_encryption_layer.cpp index 902841c77..5c84bb0a4 100644 --- a/src/core/crypto/ctr_encryption_layer.cpp +++ b/src/core/crypto/ctr_encryption_layer.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "core/crypto/ctr_encryption_layer.h" | 8 | #include "core/crypto/ctr_encryption_layer.h" |
| @@ -10,8 +11,7 @@ namespace Core::Crypto { | |||
| 10 | 11 | ||
| 11 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, | 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, |
| 12 | std::size_t base_offset) | 13 | std::size_t base_offset) |
| 13 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR), | 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR) {} |
| 14 | iv(16, 0) {} | ||
| 15 | 15 | ||
| 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { | 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 17 | if (length == 0) | 17 | if (length == 0) |
| @@ -39,9 +39,8 @@ std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t o | |||
| 39 | return read + Read(data + read, length - read, offset + read); | 39 | return read + Read(data + read, length - read, offset + read); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | void CTREncryptionLayer::SetIV(const std::vector<u8>& iv_) { | 42 | void CTREncryptionLayer::SetIV(const IVData& iv_) { |
| 43 | const auto length = std::min(iv_.size(), iv.size()); | 43 | iv = iv_; |
| 44 | iv.assign(iv_.cbegin(), iv_.cbegin() + length); | ||
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | void CTREncryptionLayer::UpdateIV(std::size_t offset) const { | 46 | void CTREncryptionLayer::UpdateIV(std::size_t offset) const { |
diff --git a/src/core/crypto/ctr_encryption_layer.h b/src/core/crypto/ctr_encryption_layer.h index a7bf810f4..a2429f001 100644 --- a/src/core/crypto/ctr_encryption_layer.h +++ b/src/core/crypto/ctr_encryption_layer.h | |||
| @@ -4,7 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | 7 | #include <array> |
| 8 | |||
| 8 | #include "core/crypto/aes_util.h" | 9 | #include "core/crypto/aes_util.h" |
| 9 | #include "core/crypto/encryption_layer.h" | 10 | #include "core/crypto/encryption_layer.h" |
| 10 | #include "core/crypto/key_manager.h" | 11 | #include "core/crypto/key_manager.h" |
| @@ -14,18 +15,20 @@ namespace Core::Crypto { | |||
| 14 | // Sits on top of a VirtualFile and provides CTR-mode AES decription. | 15 | // Sits on top of a VirtualFile and provides CTR-mode AES decription. |
| 15 | class CTREncryptionLayer : public EncryptionLayer { | 16 | class CTREncryptionLayer : public EncryptionLayer { |
| 16 | public: | 17 | public: |
| 18 | using IVData = std::array<u8, 16>; | ||
| 19 | |||
| 17 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); | 20 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); |
| 18 | 21 | ||
| 19 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; | 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; |
| 20 | 23 | ||
| 21 | void SetIV(const std::vector<u8>& iv); | 24 | void SetIV(const IVData& iv); |
| 22 | 25 | ||
| 23 | private: | 26 | private: |
| 24 | std::size_t base_offset; | 27 | std::size_t base_offset; |
| 25 | 28 | ||
| 26 | // Must be mutable as operations modify cipher contexts. | 29 | // Must be mutable as operations modify cipher contexts. |
| 27 | mutable AESCipher<Key128> cipher; | 30 | mutable AESCipher<Key128> cipher; |
| 28 | mutable std::vector<u8> iv; | 31 | mutable IVData iv{}; |
| 29 | 32 | ||
| 30 | void UpdateIV(std::size_t offset) const; | 33 | void UpdateIV(std::size_t offset) const; |
| 31 | }; | 34 | }; |
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index f87fe0abc..c09f7ad41 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -40,12 +40,14 @@ namespace Core::Crypto { | |||
| 40 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; | 40 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; |
| 41 | constexpr u64 FULL_TICKET_SIZE = 0x400; | 41 | constexpr u64 FULL_TICKET_SIZE = 0x400; |
| 42 | 42 | ||
| 43 | using namespace Common; | 43 | using Common::AsArray; |
| 44 | 44 | ||
| 45 | const std::array<SHA256Hash, 2> eticket_source_hashes{ | 45 | // clang-format off |
| 46 | "B71DB271DC338DF380AA2C4335EF8873B1AFD408E80B3582D8719FC81C5E511C"_array32, // eticket_rsa_kek_source | 46 | constexpr std::array eticket_source_hashes{ |
| 47 | "E8965A187D30E57869F562D04383C996DE487BBA5761363D2D4D32391866A85C"_array32, // eticket_rsa_kekek_source | 47 | AsArray("B71DB271DC338DF380AA2C4335EF8873B1AFD408E80B3582D8719FC81C5E511C"), // eticket_rsa_kek_source |
| 48 | AsArray("E8965A187D30E57869F562D04383C996DE487BBA5761363D2D4D32391866A85C"), // eticket_rsa_kekek_source | ||
| 48 | }; | 49 | }; |
| 50 | // clang-format on | ||
| 49 | 51 | ||
| 50 | const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ | 52 | const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ |
| 51 | {{S128KeyType::Master, 0}, "master_key_"}, | 53 | {{S128KeyType::Master, 0}, "master_key_"}, |
diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 7ed71ac3a..3e96f7516 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include "core/file_sys/vfs_offset.h" | 27 | #include "core/file_sys/vfs_offset.h" |
| 28 | #include "core/file_sys/vfs_vector.h" | 28 | #include "core/file_sys/vfs_vector.h" |
| 29 | 29 | ||
| 30 | using namespace Common; | 30 | using Common::AsArray; |
| 31 | 31 | ||
| 32 | namespace Core::Crypto { | 32 | namespace Core::Crypto { |
| 33 | 33 | ||
| @@ -47,105 +47,123 @@ struct Package2Header { | |||
| 47 | }; | 47 | }; |
| 48 | static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size."); | 48 | static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size."); |
| 49 | 49 | ||
| 50 | const std::array<SHA256Hash, 0x10> source_hashes{ | 50 | // clang-format off |
| 51 | "B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"_array32, // keyblob_mac_key_source | 51 | constexpr std::array source_hashes{ |
| 52 | "7944862A3A5C31C6720595EFD302245ABD1B54CCDCF33000557681E65C5664A4"_array32, // master_key_source | 52 | AsArray("B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"), // keyblob_mac_key_source |
| 53 | "21E2DF100FC9E094DB51B47B9B1D6E94ED379DB8B547955BEF8FE08D8DD35603"_array32, // package2_key_source | 53 | AsArray("7944862A3A5C31C6720595EFD302245ABD1B54CCDCF33000557681E65C5664A4"), // master_key_source |
| 54 | "FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"_array32, // aes_kek_generation_source | 54 | AsArray("21E2DF100FC9E094DB51B47B9B1D6E94ED379DB8B547955BEF8FE08D8DD35603"), // package2_key_source |
| 55 | "FBD10056999EDC7ACDB96098E47E2C3606230270D23281E671F0F389FC5BC585"_array32, // aes_key_generation_source | 55 | AsArray("FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"), // aes_kek_generation_source |
| 56 | "C48B619827986C7F4E3081D59DB2B460C84312650E9A8E6B458E53E8CBCA4E87"_array32, // titlekek_source | 56 | AsArray("FBD10056999EDC7ACDB96098E47E2C3606230270D23281E671F0F389FC5BC585"), // aes_key_generation_source |
| 57 | "04AD66143C726B2A139FB6B21128B46F56C553B2B3887110304298D8D0092D9E"_array32, // key_area_key_application_source | 57 | AsArray("C48B619827986C7F4E3081D59DB2B460C84312650E9A8E6B458E53E8CBCA4E87"), // titlekek_source |
| 58 | "FD434000C8FF2B26F8E9A9D2D2C12F6BE5773CBB9DC86300E1BD99F8EA33A417"_array32, // key_area_key_ocean_source | 58 | AsArray("04AD66143C726B2A139FB6B21128B46F56C553B2B3887110304298D8D0092D9E"), // key_area_key_application_source |
| 59 | "1F17B1FD51AD1C2379B58F152CA4912EC2106441E51722F38700D5937A1162F7"_array32, // key_area_key_system_source | 59 | AsArray("FD434000C8FF2B26F8E9A9D2D2C12F6BE5773CBB9DC86300E1BD99F8EA33A417"), // key_area_key_ocean_source |
| 60 | "6B2ED877C2C52334AC51E59ABFA7EC457F4A7D01E46291E9F2EAA45F011D24B7"_array32, // sd_card_kek_source | 60 | AsArray("1F17B1FD51AD1C2379B58F152CA4912EC2106441E51722F38700D5937A1162F7"), // key_area_key_system_source |
| 61 | "D482743563D3EA5DCDC3B74E97C9AC8A342164FA041A1DC80F17F6D31E4BC01C"_array32, // sd_card_save_key_source | 61 | AsArray("6B2ED877C2C52334AC51E59ABFA7EC457F4A7D01E46291E9F2EAA45F011D24B7"), // sd_card_kek_source |
| 62 | "2E751CECF7D93A2B957BD5FFCB082FD038CC2853219DD3092C6DAB9838F5A7CC"_array32, // sd_card_nca_key_source | 62 | AsArray("D482743563D3EA5DCDC3B74E97C9AC8A342164FA041A1DC80F17F6D31E4BC01C"), // sd_card_save_key_source |
| 63 | "1888CAED5551B3EDE01499E87CE0D86827F80820EFB275921055AA4E2ABDFFC2"_array32, // header_kek_source | 63 | AsArray("2E751CECF7D93A2B957BD5FFCB082FD038CC2853219DD3092C6DAB9838F5A7CC"), // sd_card_nca_key_source |
| 64 | "8F783E46852DF6BE0BA4E19273C4ADBAEE16380043E1B8C418C4089A8BD64AA6"_array32, // header_key_source | 64 | AsArray("1888CAED5551B3EDE01499E87CE0D86827F80820EFB275921055AA4E2ABDFFC2"), // header_kek_source |
| 65 | "D1757E52F1AE55FA882EC690BC6F954AC46A83DC22F277F8806BD55577C6EED7"_array32, // rsa_kek_seed3 | 65 | AsArray("8F783E46852DF6BE0BA4E19273C4ADBAEE16380043E1B8C418C4089A8BD64AA6"), // header_key_source |
| 66 | "FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"_array32, // rsa_kek_mask0 | 66 | AsArray("D1757E52F1AE55FA882EC690BC6F954AC46A83DC22F277F8806BD55577C6EED7"), // rsa_kek_seed3 |
| 67 | AsArray("FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"), // rsa_kek_mask0 | ||
| 67 | }; | 68 | }; |
| 68 | 69 | // clang-format on | |
| 69 | const std::array<SHA256Hash, 0x20> keyblob_source_hashes{ | 70 | |
| 70 | "8A06FE274AC491436791FDB388BCDD3AB9943BD4DEF8094418CDAC150FD73786"_array32, // keyblob_key_source_00 | 71 | // clang-format off |
| 71 | "2D5CAEB2521FEF70B47E17D6D0F11F8CE2C1E442A979AD8035832C4E9FBCCC4B"_array32, // keyblob_key_source_01 | 72 | constexpr std::array keyblob_source_hashes{ |
| 72 | "61C5005E713BAE780641683AF43E5F5C0E03671117F702F401282847D2FC6064"_array32, // keyblob_key_source_02 | 73 | AsArray("8A06FE274AC491436791FDB388BCDD3AB9943BD4DEF8094418CDAC150FD73786"), // keyblob_key_source_00 |
| 73 | "8E9795928E1C4428E1B78F0BE724D7294D6934689C11B190943923B9D5B85903"_array32, // keyblob_key_source_03 | 74 | AsArray("2D5CAEB2521FEF70B47E17D6D0F11F8CE2C1E442A979AD8035832C4E9FBCCC4B"), // keyblob_key_source_01 |
| 74 | "95FA33AF95AFF9D9B61D164655B32710ED8D615D46C7D6CC3CC70481B686B402"_array32, // keyblob_key_source_04 | 75 | AsArray("61C5005E713BAE780641683AF43E5F5C0E03671117F702F401282847D2FC6064"), // keyblob_key_source_02 |
| 75 | "3F5BE7B3C8B1ABD8C10B4B703D44766BA08730562C172A4FE0D6B866B3E2DB3E"_array32, // keyblob_key_source_05 | 76 | AsArray("8E9795928E1C4428E1B78F0BE724D7294D6934689C11B190943923B9D5B85903"), // keyblob_key_source_03 |
| 76 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_06 | 77 | AsArray("95FA33AF95AFF9D9B61D164655B32710ED8D615D46C7D6CC3CC70481B686B402"), // keyblob_key_source_04 |
| 77 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_07 | 78 | AsArray("3F5BE7B3C8B1ABD8C10B4B703D44766BA08730562C172A4FE0D6B866B3E2DB3E"), // keyblob_key_source_05 |
| 78 | 79 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_06 | |
| 79 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_08 | 80 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_07 |
| 80 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_09 | 81 | |
| 81 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0A | 82 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_08 |
| 82 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0B | 83 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_09 |
| 83 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0C | 84 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0A |
| 84 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0D | 85 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0B |
| 85 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0E | 86 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0C |
| 86 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0F | 87 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0D |
| 87 | 88 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0E | |
| 88 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_10 | 89 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0F |
| 89 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_11 | 90 | |
| 90 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_12 | 91 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_10 |
| 91 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_13 | 92 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_11 |
| 92 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_14 | 93 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_12 |
| 93 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_15 | 94 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_13 |
| 94 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_16 | 95 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_14 |
| 95 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_17 | 96 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_15 |
| 96 | 97 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_16 | |
| 97 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_18 | 98 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_17 |
| 98 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_19 | 99 | |
| 99 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1A | 100 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_18 |
| 100 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1B | 101 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_19 |
| 101 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1C | 102 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1A |
| 102 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1D | 103 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1B |
| 103 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1E | 104 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1C |
| 104 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1F | 105 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1D |
| 106 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1E | ||
| 107 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1F | ||
| 105 | }; | 108 | }; |
| 106 | 109 | // clang-format on | |
| 107 | const std::array<SHA256Hash, 0x20> master_key_hashes{ | 110 | |
| 108 | "0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"_array32, // master_key_00 | 111 | // clang-format off |
| 109 | "4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"_array32, // master_key_01 | 112 | constexpr std::array master_key_hashes{ |
| 110 | "79277C0237A2252EC3DFAC1F7C359C2B3D121E9DB15BB9AB4C2B4408D2F3AE09"_array32, // master_key_02 | 113 | AsArray("0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"), // master_key_00 |
| 111 | "4F36C565D13325F65EE134073C6A578FFCB0008E02D69400836844EAB7432754"_array32, // master_key_03 | 114 | AsArray("4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"), // master_key_01 |
| 112 | "75FF1D95D26113550EE6FCC20ACB58E97EDEB3A2FF52543ED5AEC63BDCC3DA50"_array32, // master_key_04 | 115 | AsArray("79277C0237A2252EC3DFAC1F7C359C2B3D121E9DB15BB9AB4C2B4408D2F3AE09"), // master_key_02 |
| 113 | "EBE2BCD6704673EC0F88A187BB2AD9F1CC82B718C389425941BDC194DC46B0DD"_array32, // master_key_05 | 116 | AsArray("4F36C565D13325F65EE134073C6A578FFCB0008E02D69400836844EAB7432754"), // master_key_03 |
| 114 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_06 | 117 | AsArray("75FF1D95D26113550EE6FCC20ACB58E97EDEB3A2FF52543ED5AEC63BDCC3DA50"), // master_key_04 |
| 115 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_07 | 118 | AsArray("EBE2BCD6704673EC0F88A187BB2AD9F1CC82B718C389425941BDC194DC46B0DD"), // master_key_05 |
| 116 | 119 | AsArray("9497E6779F5D840F2BBA1DE4E95BA1D6F21EFC94717D5AE5CA37D7EC5BD37A19"), // master_key_06 | |
| 117 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_08 | 120 | AsArray("4EC96B8CB01B8DCE382149443430B2B6EBCB2983348AFA04A25E53609DABEDF6"), // master_key_07 |
| 118 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_09 | 121 | |
| 119 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0A | 122 | AsArray("2998E2E23609BC2675FF062A2D64AF5B1B78DFF463B24119D64A1B64F01B2D51"), // master_key_08 |
| 120 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0B | 123 | AsArray("9D486A98067C44B37CF173D3BF577891EB6081FF6B4A166347D9DBBF7025076B"), // master_key_09 |
| 121 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0C | 124 | AsArray("4EC5A237A75A083A9C5F6CF615601522A7F822D06BD4BA32612C9CEBBB29BD45"), // master_key_0A |
| 122 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0D | 125 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0B |
| 123 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0E | 126 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0C |
| 124 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0F | 127 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0D |
| 125 | 128 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0E | |
| 126 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_10 | 129 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0F |
| 127 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_11 | 130 | |
| 128 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_12 | 131 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_10 |
| 129 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_13 | 132 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_11 |
| 130 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_14 | 133 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_12 |
| 131 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_15 | 134 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_13 |
| 132 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_16 | 135 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_14 |
| 133 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_17 | 136 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_15 |
| 134 | 137 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_16 | |
| 135 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_18 | 138 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_17 |
| 136 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_19 | 139 | |
| 137 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1A | 140 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_18 |
| 138 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1B | 141 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_19 |
| 139 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1C | 142 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1A |
| 140 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1D | 143 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1B |
| 141 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1E | 144 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1C |
| 142 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1F | 145 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1D |
| 146 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1E | ||
| 147 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1F | ||
| 143 | }; | 148 | }; |
| 149 | // clang-format on | ||
| 150 | |||
| 151 | static constexpr u8 CalculateMaxKeyblobSourceHash() { | ||
| 152 | const auto is_zero = [](const auto& data) { | ||
| 153 | // TODO: Replace with std::all_of whenever mingw decides to update their | ||
| 154 | // libraries to include the constexpr variant of it. | ||
| 155 | for (const auto element : data) { | ||
| 156 | if (element != 0) { | ||
| 157 | return false; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | return true; | ||
| 161 | }; | ||
| 144 | 162 | ||
| 145 | static u8 CalculateMaxKeyblobSourceHash() { | ||
| 146 | for (s8 i = 0x1F; i >= 0; --i) { | 163 | for (s8 i = 0x1F; i >= 0; --i) { |
| 147 | if (keyblob_source_hashes[i] != SHA256Hash{}) | 164 | if (!is_zero(keyblob_source_hashes[i])) { |
| 148 | return static_cast<u8>(i + 1); | 165 | return static_cast<u8>(i + 1); |
| 166 | } | ||
| 149 | } | 167 | } |
| 150 | 168 | ||
| 151 | return 0; | 169 | return 0; |
| @@ -346,10 +364,9 @@ FileSys::VirtualFile PartitionDataManager::GetPackage2Raw(Package2Type type) con | |||
| 346 | } | 364 | } |
| 347 | 365 | ||
| 348 | static bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) { | 366 | static bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) { |
| 349 | const std::vector<u8> iv(header.header_ctr.begin(), header.header_ctr.end()); | ||
| 350 | Package2Header temp = header; | 367 | Package2Header temp = header; |
| 351 | AESCipher<Key128> cipher(key, Mode::CTR); | 368 | AESCipher<Key128> cipher(key, Mode::CTR); |
| 352 | cipher.SetIV(iv); | 369 | cipher.SetIV(header.header_ctr); |
| 353 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr, | 370 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr, |
| 354 | Op::Decrypt); | 371 | Op::Decrypt); |
| 355 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { | 372 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { |
| @@ -388,7 +405,7 @@ void PartitionDataManager::DecryptPackage2(const std::array<Key128, 0x20>& packa | |||
| 388 | auto c = a->ReadAllBytes(); | 405 | auto c = a->ReadAllBytes(); |
| 389 | 406 | ||
| 390 | AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR); | 407 | AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR); |
| 391 | cipher.SetIV({header.section_ctr[1].begin(), header.section_ctr[1].end()}); | 408 | cipher.SetIV(header.section_ctr[1]); |
| 392 | cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); | 409 | cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); |
| 393 | 410 | ||
| 394 | const auto ini_file = std::make_shared<FileSys::VectorVfsFile>(c); | 411 | const auto ini_file = std::make_shared<FileSys::VectorVfsFile>(c); |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 473245d5a..5039341c7 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -495,9 +495,10 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s | |||
| 495 | 495 | ||
| 496 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key, | 496 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key, |
| 497 | starting_offset); | 497 | starting_offset); |
| 498 | std::vector<u8> iv(16); | 498 | Core::Crypto::CTREncryptionLayer::IVData iv{}; |
| 499 | for (u8 i = 0; i < 8; ++i) | 499 | for (std::size_t i = 0; i < 8; ++i) { |
| 500 | iv[i] = s_header.raw.section_ctr[0x8 - i - 1]; | 500 | iv[i] = s_header.raw.section_ctr[8 - i - 1]; |
| 501 | } | ||
| 501 | out->SetIV(iv); | 502 | out->SetIV(iv); |
| 502 | return std::static_pointer_cast<VfsFile>(out); | 503 | return std::static_pointer_cast<VfsFile>(out); |
| 503 | } | 504 | } |
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index 0090cc6c4..fe7375e84 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 6 | #include <cstddef> | 7 | #include <cstddef> |
| 7 | #include <cstring> | 8 | #include <cstring> |
| 8 | 9 | ||
| @@ -66,7 +67,7 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { | |||
| 66 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); | 67 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); |
| 67 | 68 | ||
| 68 | // Calculate AES IV | 69 | // Calculate AES IV |
| 69 | std::vector<u8> iv(16); | 70 | std::array<u8, 16> iv{}; |
| 70 | auto subsection_ctr = subsection.ctr; | 71 | auto subsection_ctr = subsection.ctr; |
| 71 | auto offset_iv = section_offset + base_offset; | 72 | auto offset_iv = section_offset + base_offset; |
| 72 | for (std::size_t i = 0; i < section_ctr.size(); ++i) | 73 | for (std::size_t i = 0; i < section_ctr.size(); ++i) |
diff --git a/src/core/file_sys/system_archive/mii_model.cpp b/src/core/file_sys/system_archive/mii_model.cpp index 61bb67945..d65c7d234 100644 --- a/src/core/file_sys/system_archive/mii_model.cpp +++ b/src/core/file_sys/system_archive/mii_model.cpp | |||
| @@ -27,18 +27,12 @@ VirtualDir MiiModel() { | |||
| 27 | auto out = std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, | 27 | auto out = std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, |
| 28 | std::vector<VirtualDir>{}, "data"); | 28 | std::vector<VirtualDir>{}, "data"); |
| 29 | 29 | ||
| 30 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_LINEAR.size()>>( | 30 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat")); |
| 31 | MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat")); | 31 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat")); |
| 32 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_SRGB.size()>>( | 32 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat")); |
| 33 | MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat")); | 33 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat")); |
| 34 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_LINEAR.size()>>( | 34 | out->AddFile(MakeArrayFile(MiiModelData::SHAPE_HIGH, "ShapeHigh.dat")); |
| 35 | MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat")); | 35 | out->AddFile(MakeArrayFile(MiiModelData::SHAPE_MID, "ShapeMid.dat")); |
| 36 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_SRGB.size()>>( | ||
| 37 | MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat")); | ||
| 38 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_HIGH.size()>>( | ||
| 39 | MiiModelData::SHAPE_HIGH, "ShapeHigh.dat")); | ||
| 40 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>( | ||
| 41 | MiiModelData::SHAPE_MID, "ShapeMid.dat")); | ||
| 42 | 36 | ||
| 43 | return out; | 37 | return out; |
| 44 | } | 38 | } |
diff --git a/src/core/file_sys/system_archive/ng_word.cpp b/src/core/file_sys/system_archive/ng_word.cpp index f4443784d..100d3c5db 100644 --- a/src/core/file_sys/system_archive/ng_word.cpp +++ b/src/core/file_sys/system_archive/ng_word.cpp | |||
| @@ -24,19 +24,18 @@ constexpr std::array<u8, 30> WORD_TXT{ | |||
| 24 | } // namespace NgWord1Data | 24 | } // namespace NgWord1Data |
| 25 | 25 | ||
| 26 | VirtualDir NgWord1() { | 26 | VirtualDir NgWord1() { |
| 27 | std::vector<VirtualFile> files(NgWord1Data::NUMBER_WORD_TXT_FILES); | 27 | std::vector<VirtualFile> files; |
| 28 | files.reserve(NgWord1Data::NUMBER_WORD_TXT_FILES); | ||
| 28 | 29 | ||
| 29 | for (std::size_t i = 0; i < files.size(); ++i) { | 30 | for (std::size_t i = 0; i < files.size(); ++i) { |
| 30 | files[i] = std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | 31 | files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, fmt::format("{}.txt", i))); |
| 31 | NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)); | ||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | 34 | files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, "common.txt")); |
| 35 | NgWord1Data::WORD_TXT, "common.txt")); | 35 | files.push_back(MakeArrayFile(NgWord1Data::VERSION_DAT, "version.dat")); |
| 36 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::VERSION_DAT.size()>>( | ||
| 37 | NgWord1Data::VERSION_DAT, "version.dat")); | ||
| 38 | 36 | ||
| 39 | return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | 37 | return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{}, |
| 38 | "data"); | ||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | namespace NgWord2Data { | 41 | namespace NgWord2Data { |
| @@ -55,27 +54,22 @@ constexpr std::array<u8, 0x2C> AC_NX_DATA{ | |||
| 55 | } // namespace NgWord2Data | 54 | } // namespace NgWord2Data |
| 56 | 55 | ||
| 57 | VirtualDir NgWord2() { | 56 | VirtualDir NgWord2() { |
| 58 | std::vector<VirtualFile> files(NgWord2Data::NUMBER_AC_NX_FILES * 3); | 57 | std::vector<VirtualFile> files; |
| 58 | files.reserve(NgWord2Data::NUMBER_AC_NX_FILES * 3); | ||
| 59 | 59 | ||
| 60 | for (std::size_t i = 0; i < NgWord2Data::NUMBER_AC_NX_FILES; ++i) { | 60 | for (std::size_t i = 0; i < NgWord2Data::NUMBER_AC_NX_FILES; ++i) { |
| 61 | files[3 * i] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 61 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i))); |
| 62 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i)); | 62 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i))); |
| 63 | files[3 * i + 1] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 63 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i))); |
| 64 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i)); | ||
| 65 | files[3 * i + 2] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | ||
| 66 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i)); | ||
| 67 | } | 64 | } |
| 68 | 65 | ||
| 69 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 66 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b1_nx")); |
| 70 | NgWord2Data::AC_NX_DATA, "ac_common_b1_nx")); | 67 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b2_nx")); |
| 71 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 68 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx")); |
| 72 | NgWord2Data::AC_NX_DATA, "ac_common_b2_nx")); | 69 | files.push_back(MakeArrayFile(NgWord2Data::VERSION_DAT, "version.dat")); |
| 73 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | ||
| 74 | NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx")); | ||
| 75 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::VERSION_DAT.size()>>( | ||
| 76 | NgWord2Data::VERSION_DAT, "version.dat")); | ||
| 77 | 70 | ||
| 78 | return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | 71 | return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{}, |
| 72 | "data"); | ||
| 79 | } | 73 | } |
| 80 | 74 | ||
| 81 | } // namespace FileSys::SystemArchive | 75 | } // namespace FileSys::SystemArchive |
diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp index d1de63f20..8fd005012 100644 --- a/src/core/file_sys/system_archive/time_zone_binary.cpp +++ b/src/core/file_sys/system_archive/time_zone_binary.cpp | |||
| @@ -654,12 +654,13 @@ static VirtualFile GenerateDefaultTimeZoneFile() { | |||
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | VirtualDir TimeZoneBinary() { | 656 | VirtualDir TimeZoneBinary() { |
| 657 | const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>( | 657 | std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>( |
| 658 | std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{}, | 658 | std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{}, |
| 659 | "zoneinfo")}; | 659 | "zoneinfo")}; |
| 660 | const std::vector<VirtualFile> root_files{ | 660 | std::vector<VirtualFile> root_files{MakeArrayFile(LOCATION_NAMES, "binaryList.txt")}; |
| 661 | std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")}; | 661 | |
| 662 | return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data"); | 662 | return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(root_dirs), |
| 663 | "data"); | ||
| 663 | } | 664 | } |
| 664 | 665 | ||
| 665 | } // namespace FileSys::SystemArchive | 666 | } // namespace FileSys::SystemArchive |
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index ac36cb2ee..95d3da2f2 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -4,7 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 7 | #include <cstring> | 8 | #include <cstring> |
| 9 | #include <memory> | ||
| 10 | #include <string> | ||
| 11 | #include <vector> | ||
| 8 | #include "core/file_sys/vfs.h" | 12 | #include "core/file_sys/vfs.h" |
| 9 | 13 | ||
| 10 | namespace FileSys { | 14 | namespace FileSys { |
| @@ -13,7 +17,8 @@ namespace FileSys { | |||
| 13 | template <std::size_t size> | 17 | template <std::size_t size> |
| 14 | class ArrayVfsFile : public VfsFile { | 18 | class ArrayVfsFile : public VfsFile { |
| 15 | public: | 19 | public: |
| 16 | ArrayVfsFile(std::array<u8, size> data, std::string name = "", VirtualDir parent = nullptr) | 20 | explicit ArrayVfsFile(const std::array<u8, size>& data, std::string name = "", |
| 21 | VirtualDir parent = nullptr) | ||
| 17 | : data(data), name(std::move(name)), parent(std::move(parent)) {} | 22 | : data(data), name(std::move(name)), parent(std::move(parent)) {} |
| 18 | 23 | ||
| 19 | std::string GetName() const override { | 24 | std::string GetName() const override { |
| @@ -61,6 +66,12 @@ private: | |||
| 61 | VirtualDir parent; | 66 | VirtualDir parent; |
| 62 | }; | 67 | }; |
| 63 | 68 | ||
| 69 | template <std::size_t Size, typename... Args> | ||
| 70 | std::shared_ptr<ArrayVfsFile<Size>> MakeArrayFile(const std::array<u8, Size>& data, | ||
| 71 | Args&&... args) { | ||
| 72 | return std::make_shared<ArrayVfsFile<Size>>(data, std::forward<Args>(args)...); | ||
| 73 | } | ||
| 74 | |||
| 64 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction | 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction |
| 65 | class VectorVfsFile : public VfsFile { | 76 | class VectorVfsFile : public VfsFile { |
| 66 | public: | 77 | public: |
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 0dc6a4a43..1b503331f 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -229,6 +229,8 @@ inline void ResponseBuilder::Push(u32 value) { | |||
| 229 | 229 | ||
| 230 | template <typename T> | 230 | template <typename T> |
| 231 | void ResponseBuilder::PushRaw(const T& value) { | 231 | void ResponseBuilder::PushRaw(const T& value) { |
| 232 | static_assert(std::is_trivially_copyable_v<T>, | ||
| 233 | "It's undefined behavior to use memcpy with non-trivially copyable objects"); | ||
| 232 | std::memcpy(cmdbuf + index, &value, sizeof(T)); | 234 | std::memcpy(cmdbuf + index, &value, sizeof(T)); |
| 233 | index += (sizeof(T) + 3) / 4; // round up to word length | 235 | index += (sizeof(T) + 3) / 4; // round up to word length |
| 234 | } | 236 | } |
| @@ -384,6 +386,8 @@ inline s32 RequestParser::Pop() { | |||
| 384 | 386 | ||
| 385 | template <typename T> | 387 | template <typename T> |
| 386 | void RequestParser::PopRaw(T& value) { | 388 | void RequestParser::PopRaw(T& value) { |
| 389 | static_assert(std::is_trivially_copyable_v<T>, | ||
| 390 | "It's undefined behavior to use memcpy with non-trivially copyable objects"); | ||
| 387 | std::memcpy(&value, cmdbuf + index, sizeof(T)); | 391 | std::memcpy(&value, cmdbuf + index, sizeof(T)); |
| 388 | index += (sizeof(T) + 3) / 4; // round up to word length | 392 | index += (sizeof(T) + 3) / 4; // round up to word length |
| 389 | } | 393 | } |
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index df0debe1b..b882eaa0f 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -81,7 +81,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 | |||
| 81 | do { | 81 | do { |
| 82 | current_value = monitor.ExclusiveRead32(current_core, address); | 82 | current_value = monitor.ExclusiveRead32(current_core, address); |
| 83 | 83 | ||
| 84 | if (current_value != value) { | 84 | if (current_value != static_cast<u32>(value)) { |
| 85 | return ERR_INVALID_STATE; | 85 | return ERR_INVALID_STATE; |
| 86 | } | 86 | } |
| 87 | current_value++; | 87 | current_value++; |
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 5d6aac00f..e22e07206 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp | |||
| @@ -604,7 +604,6 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis | |||
| 604 | if (const auto result{ | 604 | if (const auto result{ |
| 605 | Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; | 605 | Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; |
| 606 | result.IsError()) { | 606 | result.IsError()) { |
| 607 | const MemoryInfo info{block_manager->FindBlock(cur_addr).GetMemoryInfo()}; | ||
| 608 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; | 607 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; |
| 609 | 608 | ||
| 610 | ASSERT( | 609 | ASSERT( |
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index f93e5e4b0..a4b234424 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -131,7 +131,8 @@ u32 GlobalScheduler::SelectThreads() { | |||
| 131 | u32 cores_needing_context_switch{}; | 131 | u32 cores_needing_context_switch{}; |
| 132 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 132 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 133 | Scheduler& sched = kernel.Scheduler(core); | 133 | Scheduler& sched = kernel.Scheduler(core); |
| 134 | ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core); | 134 | ASSERT(top_threads[core] == nullptr || |
| 135 | static_cast<u32>(top_threads[core]->GetProcessorID()) == core); | ||
| 135 | if (update_thread(top_threads[core], sched)) { | 136 | if (update_thread(top_threads[core], sched)) { |
| 136 | cores_needing_context_switch |= (1ul << core); | 137 | cores_needing_context_switch |= (1ul << core); |
| 137 | } | 138 | } |
| @@ -663,32 +664,26 @@ void Scheduler::Reload() { | |||
| 663 | } | 664 | } |
| 664 | 665 | ||
| 665 | void Scheduler::SwitchContextStep2() { | 666 | void Scheduler::SwitchContextStep2() { |
| 666 | Thread* previous_thread = current_thread_prev.get(); | ||
| 667 | Thread* new_thread = selected_thread.get(); | ||
| 668 | |||
| 669 | // Load context of new thread | 667 | // Load context of new thread |
| 670 | Process* const previous_process = | 668 | if (selected_thread) { |
| 671 | previous_thread != nullptr ? previous_thread->GetOwnerProcess() : nullptr; | 669 | ASSERT_MSG(selected_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, |
| 672 | |||
| 673 | if (new_thread) { | ||
| 674 | ASSERT_MSG(new_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, | ||
| 675 | "Thread must be runnable."); | 670 | "Thread must be runnable."); |
| 676 | 671 | ||
| 677 | // Cancel any outstanding wakeup events for this thread | 672 | // Cancel any outstanding wakeup events for this thread |
| 678 | new_thread->SetIsRunning(true); | 673 | selected_thread->SetIsRunning(true); |
| 679 | new_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); | 674 | selected_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); |
| 680 | new_thread->SetWasRunning(false); | 675 | selected_thread->SetWasRunning(false); |
| 681 | 676 | ||
| 682 | auto* const thread_owner_process = current_thread->GetOwnerProcess(); | 677 | auto* const thread_owner_process = current_thread->GetOwnerProcess(); |
| 683 | if (thread_owner_process != nullptr) { | 678 | if (thread_owner_process != nullptr) { |
| 684 | system.Kernel().MakeCurrentProcess(thread_owner_process); | 679 | system.Kernel().MakeCurrentProcess(thread_owner_process); |
| 685 | } | 680 | } |
| 686 | if (!new_thread->IsHLEThread()) { | 681 | if (!selected_thread->IsHLEThread()) { |
| 687 | Core::ARM_Interface& cpu_core = new_thread->ArmInterface(); | 682 | Core::ARM_Interface& cpu_core = selected_thread->ArmInterface(); |
| 688 | cpu_core.LoadContext(new_thread->GetContext32()); | 683 | cpu_core.LoadContext(selected_thread->GetContext32()); |
| 689 | cpu_core.LoadContext(new_thread->GetContext64()); | 684 | cpu_core.LoadContext(selected_thread->GetContext64()); |
| 690 | cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); | 685 | cpu_core.SetTlsAddress(selected_thread->GetTLSAddress()); |
| 691 | cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); | 686 | cpu_core.SetTPIDR_EL0(selected_thread->GetTPIDR_EL0()); |
| 692 | cpu_core.ChangeProcessorID(this->core_id); | 687 | cpu_core.ChangeProcessorID(this->core_id); |
| 693 | cpu_core.ClearExclusiveState(); | 688 | cpu_core.ClearExclusiveState(); |
| 694 | } | 689 | } |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 55a1edf1a..7d92b25a3 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -378,7 +378,11 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& | |||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { | 380 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { |
| 381 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 381 | IPC::RequestParser rp{ctx}; |
| 382 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 383 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 384 | |||
| 385 | screenshot_permission = permission; | ||
| 382 | 386 | ||
| 383 | IPC::ResponseBuilder rb{ctx, 2}; | 387 | IPC::ResponseBuilder rb{ctx, 2}; |
| 384 | rb.Push(RESULT_SUCCESS); | 388 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 6cfb11b48..6e69796ec 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -149,6 +149,12 @@ private: | |||
| 149 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); | 149 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); |
| 150 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); | 150 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); |
| 151 | 151 | ||
| 152 | enum class ScreenshotPermission : u32 { | ||
| 153 | Inherit = 0, | ||
| 154 | Enable = 1, | ||
| 155 | Disable = 2, | ||
| 156 | }; | ||
| 157 | |||
| 152 | Core::System& system; | 158 | Core::System& system; |
| 153 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 159 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 154 | Kernel::EventPair launchable_event; | 160 | Kernel::EventPair launchable_event; |
| @@ -157,6 +163,7 @@ private: | |||
| 157 | u32 idle_time_detection_extension = 0; | 163 | u32 idle_time_detection_extension = 0; |
| 158 | u64 num_fatal_sections_entered = 0; | 164 | u64 num_fatal_sections_entered = 0; |
| 159 | bool is_auto_sleep_disabled = false; | 165 | bool is_auto_sleep_disabled = false; |
| 166 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | ||
| 160 | }; | 167 | }; |
| 161 | 168 | ||
| 162 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 169 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index b526a94fe..aabf166b7 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -57,7 +57,7 @@ public: | |||
| 57 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); | 57 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); |
| 58 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); | 58 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); |
| 59 | 59 | ||
| 60 | template <Common::IsBaseOf<Kernel::SessionRequestHandler> T> | 60 | template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> |
| 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
| 62 | auto service = registered_services.find(service_name); | 62 | auto service = registered_services.find(service_name); |
| 63 | if (service == registered_services.end()) { | 63 | if (service == registered_services.end()) { |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index b8f8f1448..7c48e55e1 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -25,7 +25,7 @@ namespace Loader { | |||
| 25 | 25 | ||
| 26 | namespace { | 26 | namespace { |
| 27 | 27 | ||
| 28 | template <Common::IsBaseOf<AppLoader> T> | 28 | template <Common::DerivedFrom<AppLoader> T> |
| 29 | std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { | 29 | std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { |
| 30 | const auto file_type = T::IdentifyType(file); | 30 | const auto file_type = T::IdentifyType(file); |
| 31 | if (file_type != FileType::Error) { | 31 | if (file_type != FileType::Error) { |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index eeebdf02e..4b5cd0624 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -199,17 +199,29 @@ void CheatEngine::Initialize() { | |||
| 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); | 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); |
| 200 | 200 | ||
| 201 | const auto& page_table = system.CurrentProcess()->PageTable(); | 201 | const auto& page_table = system.CurrentProcess()->PageTable(); |
| 202 | metadata.heap_extents = {page_table.GetHeapRegionStart(), page_table.GetHeapRegionSize()}; | 202 | metadata.heap_extents = { |
| 203 | metadata.address_space_extents = {page_table.GetAddressSpaceStart(), | 203 | .base = page_table.GetHeapRegionStart(), |
| 204 | page_table.GetAddressSpaceSize()}; | 204 | .size = page_table.GetHeapRegionSize(), |
| 205 | metadata.alias_extents = {page_table.GetAliasCodeRegionStart(), | 205 | }; |
| 206 | page_table.GetAliasCodeRegionSize()}; | 206 | |
| 207 | metadata.address_space_extents = { | ||
| 208 | .base = page_table.GetAddressSpaceStart(), | ||
| 209 | .size = page_table.GetAddressSpaceSize(), | ||
| 210 | }; | ||
| 211 | |||
| 212 | metadata.alias_extents = { | ||
| 213 | .base = page_table.GetAliasCodeRegionStart(), | ||
| 214 | .size = page_table.GetAliasCodeRegionSize(), | ||
| 215 | }; | ||
| 207 | 216 | ||
| 208 | is_pending_reload.exchange(true); | 217 | is_pending_reload.exchange(true); |
| 209 | } | 218 | } |
| 210 | 219 | ||
| 211 | void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) { | 220 | void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) { |
| 212 | metadata.main_nso_extents = {main_region_begin, main_region_size}; | 221 | metadata.main_nso_extents = { |
| 222 | .base = main_region_begin, | ||
| 223 | .size = main_region_size, | ||
| 224 | }; | ||
| 213 | } | 225 | } |
| 214 | 226 | ||
| 215 | void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | 227 | void CheatEngine::Reload(std::vector<CheatEntry> cheats) { |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index f45983f3f..b346fdf8e 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -148,19 +148,17 @@ void GCButtonFactory::EndConfiguration() { | |||
| 148 | 148 | ||
| 149 | class GCAnalog final : public Input::AnalogDevice { | 149 | class GCAnalog final : public Input::AnalogDevice { |
| 150 | public: | 150 | public: |
| 151 | GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter) | 151 | GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter, |
| 152 | float range_) | ||
| 152 | : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), | 153 | : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), |
| 153 | origin_value_x(adapter->GetOriginValue(port_, axis_x_)), | 154 | origin_value_x(adapter->GetOriginValue(port_, axis_x_)), |
| 154 | origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {} | 155 | origin_value_y(adapter->GetOriginValue(port_, axis_y_)), range(range_) {} |
| 155 | 156 | ||
| 156 | float GetAxis(int axis) const { | 157 | float GetAxis(int axis) const { |
| 157 | if (gcadapter->DeviceConnected(port)) { | 158 | if (gcadapter->DeviceConnected(port)) { |
| 158 | std::lock_guard lock{mutex}; | 159 | std::lock_guard lock{mutex}; |
| 159 | const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; | 160 | const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; |
| 160 | // division is not by a perfect 128 to account for some variance in center location | 161 | return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range); |
| 161 | // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range | ||
| 162 | // [20-230] | ||
| 163 | return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f; | ||
| 164 | } | 162 | } |
| 165 | return 0.0f; | 163 | return 0.0f; |
| 166 | } | 164 | } |
| @@ -215,6 +213,7 @@ private: | |||
| 215 | GCAdapter::Adapter* gcadapter; | 213 | GCAdapter::Adapter* gcadapter; |
| 216 | const float origin_value_x; | 214 | const float origin_value_x; |
| 217 | const float origin_value_y; | 215 | const float origin_value_y; |
| 216 | const float range; | ||
| 218 | mutable std::mutex mutex; | 217 | mutable std::mutex mutex; |
| 219 | }; | 218 | }; |
| 220 | 219 | ||
| @@ -234,8 +233,9 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param | |||
| 234 | const int axis_x = params.Get("axis_x", 0); | 233 | const int axis_x = params.Get("axis_x", 0); |
| 235 | const int axis_y = params.Get("axis_y", 1); | 234 | const int axis_y = params.Get("axis_y", 1); |
| 236 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 235 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); |
| 236 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||
| 237 | 237 | ||
| 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get()); | 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | void GCAnalogFactory::BeginConfiguration() { | 241 | void GCAnalogFactory::BeginConfiguration() { |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 675b477fa..d76c279d3 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -66,14 +66,14 @@ public: | |||
| 66 | state.axes.insert_or_assign(axis, value); | 66 | state.axes.insert_or_assign(axis, value); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | float GetAxis(int axis) const { | 69 | float GetAxis(int axis, float range) const { |
| 70 | std::lock_guard lock{mutex}; | 70 | std::lock_guard lock{mutex}; |
| 71 | return state.axes.at(axis) / 32767.0f; | 71 | return state.axes.at(axis) / (32767.0f * range); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const { | 74 | std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const { |
| 75 | float x = GetAxis(axis_x); | 75 | float x = GetAxis(axis_x, range); |
| 76 | float y = GetAxis(axis_y); | 76 | float y = GetAxis(axis_y, range); |
| 77 | y = -y; // 3DS uses an y-axis inverse from SDL | 77 | y = -y; // 3DS uses an y-axis inverse from SDL |
| 78 | 78 | ||
| 79 | // Make sure the coordinates are in the unit circle, | 79 | // Make sure the coordinates are in the unit circle, |
| @@ -313,7 +313,7 @@ public: | |||
| 313 | trigger_if_greater(trigger_if_greater_) {} | 313 | trigger_if_greater(trigger_if_greater_) {} |
| 314 | 314 | ||
| 315 | bool GetStatus() const override { | 315 | bool GetStatus() const override { |
| 316 | const float axis_value = joystick->GetAxis(axis); | 316 | const float axis_value = joystick->GetAxis(axis, 1.0f); |
| 317 | if (trigger_if_greater) { | 317 | if (trigger_if_greater) { |
| 318 | return axis_value > threshold; | 318 | return axis_value > threshold; |
| 319 | } | 319 | } |
| @@ -329,11 +329,13 @@ private: | |||
| 329 | 329 | ||
| 330 | class SDLAnalog final : public Input::AnalogDevice { | 330 | class SDLAnalog final : public Input::AnalogDevice { |
| 331 | public: | 331 | public: |
| 332 | SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_) | 332 | SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_, |
| 333 | : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_) {} | 333 | float range_) |
| 334 | : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), | ||
| 335 | range(range_) {} | ||
| 334 | 336 | ||
| 335 | std::tuple<float, float> GetStatus() const override { | 337 | std::tuple<float, float> GetStatus() const override { |
| 336 | const auto [x, y] = joystick->GetAnalog(axis_x, axis_y); | 338 | const auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range); |
| 337 | const float r = std::sqrt((x * x) + (y * y)); | 339 | const float r = std::sqrt((x * x) + (y * y)); |
| 338 | if (r > deadzone) { | 340 | if (r > deadzone) { |
| 339 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), | 341 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), |
| @@ -363,6 +365,7 @@ private: | |||
| 363 | const int axis_x; | 365 | const int axis_x; |
| 364 | const int axis_y; | 366 | const int axis_y; |
| 365 | const float deadzone; | 367 | const float deadzone; |
| 368 | const float range; | ||
| 366 | }; | 369 | }; |
| 367 | 370 | ||
| 368 | /// A button device factory that creates button devices from SDL joystick | 371 | /// A button device factory that creates button devices from SDL joystick |
| @@ -458,13 +461,13 @@ public: | |||
| 458 | const int axis_x = params.Get("axis_x", 0); | 461 | const int axis_x = params.Get("axis_x", 0); |
| 459 | const int axis_y = params.Get("axis_y", 1); | 462 | const int axis_y = params.Get("axis_y", 1); |
| 460 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 463 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); |
| 461 | 464 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | |
| 462 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 465 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 463 | 466 | ||
| 464 | // This is necessary so accessing GetAxis with axis_x and axis_y won't crash | 467 | // This is necessary so accessing GetAxis with axis_x and axis_y won't crash |
| 465 | joystick->SetAxis(axis_x, 0); | 468 | joystick->SetAxis(axis_x, 0); |
| 466 | joystick->SetAxis(axis_y, 0); | 469 | joystick->SetAxis(axis_y, 0); |
| 467 | return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone); | 470 | return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone, range); |
| 468 | } | 471 | } |
| 469 | 472 | ||
| 470 | private: | 473 | private: |
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 9a98f0e98..e614a92df 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -96,7 +96,6 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta | |||
| 96 | } | 96 | } |
| 97 | params.type = GetFormatType(params.pixel_format); | 97 | params.type = GetFormatType(params.pixel_format); |
| 98 | } | 98 | } |
| 99 | params.type = GetFormatType(params.pixel_format); | ||
| 100 | // TODO: on 1DBuffer we should use the tic info. | 99 | // TODO: on 1DBuffer we should use the tic info. |
| 101 | if (tic.IsBuffer()) { | 100 | if (tic.IsBuffer()) { |
| 102 | params.target = SurfaceTarget::TextureBuffer; | 101 | params.target = SurfaceTarget::TextureBuffer; |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 239016b94..643ca6491 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -350,6 +350,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 350 | 350 | ||
| 351 | void GameListWorker::run() { | 351 | void GameListWorker::run() { |
| 352 | stop_processing = false; | 352 | stop_processing = false; |
| 353 | provider->ClearAllEntries(); | ||
| 353 | 354 | ||
| 354 | for (UISettings::GameDir& game_dir : game_dirs) { | 355 | for (UISettings::GameDir& game_dir : game_dirs) { |
| 355 | if (game_dir.path == QStringLiteral("SDMC")) { | 356 | if (game_dir.path == QStringLiteral("SDMC")) { |
| @@ -368,7 +369,6 @@ void GameListWorker::run() { | |||
| 368 | watch_list.append(game_dir.path); | 369 | watch_list.append(game_dir.path); |
| 369 | auto* const game_list_dir = new GameListDir(game_dir); | 370 | auto* const game_list_dir = new GameListDir(game_dir); |
| 370 | emit DirEntryReady(game_list_dir); | 371 | emit DirEntryReady(game_list_dir); |
| 371 | provider->ClearAllEntries(); | ||
| 372 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), | 372 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), |
| 373 | game_dir.deep_scan ? 256 : 0, game_list_dir); | 373 | game_dir.deep_scan ? 256 : 0, game_list_dir); |
| 374 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), | 374 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), |