diff options
22 files changed, 240 insertions, 228 deletions
diff --git a/.ci/scripts/format/script.sh b/.ci/scripts/format/script.sh index 5ab828d5e..991fe1552 100644 --- a/.ci/scripts/format/script.sh +++ b/.ci/scripts/format/script.sh | |||
| @@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis | |||
| 7 | fi | 7 | fi |
| 8 | 8 | ||
| 9 | # Default clang-format points to default 3.5 version one | 9 | # Default clang-format points to default 3.5 version one |
| 10 | CLANG_FORMAT=clang-format-6.0 | 10 | CLANG_FORMAT=clang-format-10.0 |
| 11 | $CLANG_FORMAT --version | 11 | $CLANG_FORMAT --version |
| 12 | 12 | ||
| 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then | 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then |
diff --git a/.travis/clang-format/script.sh b/.travis/clang-format/script.sh index 3eff6322f..56a785fe0 100755 --- a/.travis/clang-format/script.sh +++ b/.travis/clang-format/script.sh | |||
| @@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis* | |||
| 7 | fi | 7 | fi |
| 8 | 8 | ||
| 9 | # Default clang-format points to default 3.5 version one | 9 | # Default clang-format points to default 3.5 version one |
| 10 | CLANG_FORMAT=clang-format-6.0 | 10 | CLANG_FORMAT=clang-format-10.0 |
| 11 | $CLANG_FORMAT --version | 11 | $CLANG_FORMAT --version |
| 12 | 12 | ||
| 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then | 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then |
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/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 b31a81560..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; |
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/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/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(), |