summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/scripts/format/script.sh2
-rwxr-xr-x.travis/clang-format/script.sh2
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/audio_core/cubeb_sink.cpp2
-rw-r--r--src/common/concepts.h10
-rw-r--r--src/common/detached_tasks.cpp3
-rw-r--r--src/common/hex_util.cpp34
-rw-r--r--src/common/hex_util.h29
-rw-r--r--src/common/math_util.h2
-rw-r--r--src/common/virtual_buffer.cpp9
-rw-r--r--src/core/crypto/key_manager.cpp10
-rw-r--r--src/core/crypto/partition_data_manager.cpp206
-rw-r--r--src/core/file_sys/registered_cache.h6
-rw-r--r--src/core/file_sys/system_archive/mii_model.cpp18
-rw-r--r--src/core/file_sys/system_archive/ng_word.cpp42
-rw-r--r--src/core/file_sys/system_archive/time_zone_binary.cpp9
-rw-r--r--src/core/file_sys/vfs_vector.h13
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp46
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp23
-rw-r--r--src/core/hle/kernel/scheduler.cpp31
-rw-r--r--src/core/hle/service/am/am.cpp6
-rw-r--r--src/core/hle/service/am/am.h7
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp3
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp6
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h10
-rw-r--r--src/core/hle/service/sm/sm.h2
-rw-r--r--src/core/loader/loader.cpp2
-rw-r--r--src/core/memory/cheat_engine.cpp24
-rw-r--r--src/core/tools/freezer.cpp31
-rw-r--r--src/core/tools/freezer.h7
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp14
-rw-r--r--src/input_common/sdl/sdl_impl.cpp25
-rw-r--r--src/input_common/udp/client.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/wrapper.h28
-rw-r--r--src/video_core/shader/control_flow.cpp30
-rw-r--r--src/video_core/shader/decode/memory.cpp6
-rw-r--r--src/video_core/texture_cache/surface_params.cpp1
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp61
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.cpp11
-rw-r--r--src/yuzu/game_list_worker.cpp2
43 files changed, 410 insertions, 377 deletions
diff --git a/.ci/scripts/format/script.sh b/.ci/scripts/format/script.sh
index 5ab828d5e..969ab637c 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
7fi 7fi
8 8
9# Default clang-format points to default 3.5 version one 9# Default clang-format points to default 3.5 version one
10CLANG_FORMAT=clang-format-6.0 10CLANG_FORMAT=clang-format-10
11$CLANG_FORMAT --version 11$CLANG_FORMAT --version
12 12
13if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then 13if [ "$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*
7fi 7fi
8 8
9# Default clang-format points to default 3.5 version one 9# Default clang-format points to default 3.5 version one
10CLANG_FORMAT=clang-format-6.0 10CLANG_FORMAT=clang-format-10.0
11$CLANG_FORMAT --version 11$CLANG_FORMAT --version
12 12
13if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then 13if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3282ae9d4..8ecc2e476 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -456,7 +456,7 @@ endif()
456# against all the src files. This should be used before making a pull request. 456# against all the src files. This should be used before making a pull request.
457# ======================================================================= 457# =======================================================================
458 458
459set(CLANG_FORMAT_POSTFIX "-6.0") 459set(CLANG_FORMAT_POSTFIX "-10")
460find_program(CLANG_FORMAT 460find_program(CLANG_FORMAT
461 NAMES clang-format${CLANG_FORMAT_POSTFIX} 461 NAMES clang-format${CLANG_FORMAT_POSTFIX}
462 clang-format 462 clang-format
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 41bf5cd4d..c27df946c 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -78,7 +78,7 @@ public:
78 const s16 surround_left{samples[i + 4]}; 78 const s16 surround_left{samples[i + 4]};
79 const s16 surround_right{samples[i + 5]}; 79 const s16 surround_right{samples[i + 5]};
80 // Not used in the ATSC reference implementation 80 // Not used in the ATSC reference implementation
81 [[maybe_unused]] const s16 low_frequency_effects { samples[i + 3] }; 81 [[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]};
82 82
83 constexpr s32 clev{707}; // center mixing level coefficient 83 constexpr s32 clev{707}; // center mixing level coefficient
84 constexpr s32 slev{707}; // surround mixing level coefficient 84 constexpr s32 slev{707}; // surround mixing level coefficient
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
27template <typename T, typename T2> 27// is available on all supported platforms.
28concept IsBaseOf = requires { 28template <typename Derived, typename Base>
29 std::is_base_of_v<T, T2>; 29concept 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/detached_tasks.cpp b/src/common/detached_tasks.cpp
index f268d6021..f2b4939df 100644
--- a/src/common/detached_tasks.cpp
+++ b/src/common/detached_tasks.cpp
@@ -34,8 +34,7 @@ void DetachedTasks::AddTask(std::function<void()> task) {
34 std::unique_lock lock{instance->mutex}; 34 std::unique_lock lock{instance->mutex};
35 --instance->count; 35 --instance->count;
36 std::notify_all_at_thread_exit(instance->cv, std::move(lock)); 36 std::notify_all_at_thread_exit(instance->cv, std::move(lock));
37 }) 37 }).detach();
38 .detach();
39} 38}
40 39
41} // namespace Common 40} // 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
8namespace Common { 7namespace Common {
9 8
10u8 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
21std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { 9std::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
33std::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
44std::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
15namespace Common { 15namespace Common {
16 16
17u8 ToHexNibble(char c1); 17constexpr 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
19std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); 29std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
20 30
21template <std::size_t Size, bool le = false> 31template <std::size_t Size, bool le = false>
22std::array<u8, Size> HexStringToArray(std::string_view str) { 32constexpr 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
51std::array<u8, 0x10> operator"" _array16(const char* str, std::size_t len); 63constexpr std::array<u8, 16> AsArray(const char (&data)[17]) {
52std::array<u8, 0x20> operator"" _array32(const char* str, std::size_t len); 64 return HexStringToArray<16>(data);
65}
66
67constexpr 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/math_util.h b/src/common/math_util.h
index 83ef0201f..abca3177c 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -54,6 +54,6 @@ struct Rectangle {
54}; 54};
55 55
56template <typename T> 56template <typename T>
57Rectangle(T, T, T, T)->Rectangle<T>; 57Rectangle(T, T, T, T) -> Rectangle<T>;
58 58
59} // namespace Common 59} // namespace Common
diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp
index be5b67752..b009cb500 100644
--- a/src/common/virtual_buffer.cpp
+++ b/src/common/virtual_buffer.cpp
@@ -5,16 +5,7 @@
5#ifdef _WIN32 5#ifdef _WIN32
6#include <windows.h> 6#include <windows.h>
7#else 7#else
8#include <stdio.h>
9#include <sys/mman.h> 8#include <sys/mman.h>
10#include <sys/types.h>
11#if defined __APPLE__ || defined __FreeBSD__ || defined __OpenBSD__
12#include <sys/sysctl.h>
13#elif defined __HAIKU__
14#include <OS.h>
15#else
16#include <sys/sysinfo.h>
17#endif
18#endif 9#endif
19 10
20#include "common/assert.h" 11#include "common/assert.h"
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 {
40constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; 40constexpr u64 CURRENT_CRYPTO_REVISION = 0x5;
41constexpr u64 FULL_TICKET_SIZE = 0x400; 41constexpr u64 FULL_TICKET_SIZE = 0x400;
42 42
43using namespace Common; 43using Common::AsArray;
44 44
45const std::array<SHA256Hash, 2> eticket_source_hashes{ 45// clang-format off
46 "B71DB271DC338DF380AA2C4335EF8873B1AFD408E80B3582D8719FC81C5E511C"_array32, // eticket_rsa_kek_source 46constexpr 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
50const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ 52const 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
30using namespace Common; 30using Common::AsArray;
31 31
32namespace Core::Crypto { 32namespace Core::Crypto {
33 33
@@ -47,105 +47,123 @@ struct Package2Header {
47}; 47};
48static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size."); 48static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size.");
49 49
50const std::array<SHA256Hash, 0x10> source_hashes{ 50// clang-format off
51 "B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"_array32, // keyblob_mac_key_source 51constexpr 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
69const 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 72constexpr 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
107const std::array<SHA256Hash, 0x20> master_key_hashes{ 110
108 "0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"_array32, // master_key_00 111// clang-format off
109 "4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"_array32, // master_key_01 112constexpr 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
151static 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
145static 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/registered_cache.h b/src/core/file_sys/registered_cache.h
index ec1d54f27..5b414b0f0 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -133,9 +133,9 @@ public:
133 // Parsing function defines the conversion from raw file to NCA. If there are other steps 133 // Parsing function defines the conversion from raw file to NCA. If there are other steps
134 // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom 134 // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom
135 // parsing function. 135 // parsing function.
136 explicit RegisteredCache(VirtualDir dir, 136 explicit RegisteredCache(
137 ContentProviderParsingFunction parsing_function = 137 VirtualDir dir, ContentProviderParsingFunction parsing_function =
138 [](const VirtualFile& file, const NcaID& id) { return file; }); 138 [](const VirtualFile& file, const NcaID& id) { return file; });
139 ~RegisteredCache() override; 139 ~RegisteredCache() override;
140 140
141 void Refresh() override; 141 void Refresh() override;
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
26VirtualDir NgWord1() { 26VirtualDir 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
42namespace NgWord2Data { 41namespace NgWord2Data {
@@ -55,27 +54,22 @@ constexpr std::array<u8, 0x2C> AC_NX_DATA{
55} // namespace NgWord2Data 54} // namespace NgWord2Data
56 55
57VirtualDir NgWord2() { 56VirtualDir 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
656VirtualDir TimeZoneBinary() { 656VirtualDir 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
10namespace FileSys { 14namespace FileSys {
@@ -13,7 +17,8 @@ namespace FileSys {
13template <std::size_t size> 17template <std::size_t size>
14class ArrayVfsFile : public VfsFile { 18class ArrayVfsFile : public VfsFile {
15public: 19public:
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
69template <std::size_t Size, typename... Args>
70std::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
65class VectorVfsFile : public VfsFile { 76class VectorVfsFile : public VfsFile {
66public: 77public:
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/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 9277b5d08..81f85643b 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -293,13 +293,15 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
293 BufferDescriptorA()[buffer_index].Size()}; 293 BufferDescriptorA()[buffer_index].Size()};
294 294
295 if (is_buffer_a) { 295 if (is_buffer_a) {
296 ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return buffer; }, 296 ASSERT_OR_EXECUTE_MSG(
297 "BufferDescriptorA invalid buffer_index {}", buffer_index); 297 BufferDescriptorA().size() > buffer_index, { return buffer; },
298 "BufferDescriptorA invalid buffer_index {}", buffer_index);
298 buffer.resize(BufferDescriptorA()[buffer_index].Size()); 299 buffer.resize(BufferDescriptorA()[buffer_index].Size());
299 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); 300 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size());
300 } else { 301 } else {
301 ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return buffer; }, 302 ASSERT_OR_EXECUTE_MSG(
302 "BufferDescriptorX invalid buffer_index {}", buffer_index); 303 BufferDescriptorX().size() > buffer_index, { return buffer; },
304 "BufferDescriptorX invalid buffer_index {}", buffer_index);
303 buffer.resize(BufferDescriptorX()[buffer_index].Size()); 305 buffer.resize(BufferDescriptorX()[buffer_index].Size());
304 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); 306 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size());
305 } 307 }
@@ -324,16 +326,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
324 } 326 }
325 327
326 if (is_buffer_b) { 328 if (is_buffer_b) {
327 ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index && 329 ASSERT_OR_EXECUTE_MSG(
328 BufferDescriptorB()[buffer_index].Size() >= size, 330 BufferDescriptorB().size() > buffer_index &&
329 { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", 331 BufferDescriptorB()[buffer_index].Size() >= size,
330 buffer_index, size); 332 { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size);
331 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); 333 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
332 } else { 334 } else {
333 ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index && 335 ASSERT_OR_EXECUTE_MSG(
334 BufferDescriptorC()[buffer_index].Size() >= size, 336 BufferDescriptorC().size() > buffer_index &&
335 { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", 337 BufferDescriptorC()[buffer_index].Size() >= size,
336 buffer_index, size); 338 { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size);
337 memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); 339 memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size);
338 } 340 }
339 341
@@ -344,12 +346,14 @@ std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const
344 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && 346 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
345 BufferDescriptorA()[buffer_index].Size()}; 347 BufferDescriptorA()[buffer_index].Size()};
346 if (is_buffer_a) { 348 if (is_buffer_a) {
347 ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return 0; }, 349 ASSERT_OR_EXECUTE_MSG(
348 "BufferDescriptorA invalid buffer_index {}", buffer_index); 350 BufferDescriptorA().size() > buffer_index, { return 0; },
351 "BufferDescriptorA invalid buffer_index {}", buffer_index);
349 return BufferDescriptorA()[buffer_index].Size(); 352 return BufferDescriptorA()[buffer_index].Size();
350 } else { 353 } else {
351 ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return 0; }, 354 ASSERT_OR_EXECUTE_MSG(
352 "BufferDescriptorX invalid buffer_index {}", buffer_index); 355 BufferDescriptorX().size() > buffer_index, { return 0; },
356 "BufferDescriptorX invalid buffer_index {}", buffer_index);
353 return BufferDescriptorX()[buffer_index].Size(); 357 return BufferDescriptorX()[buffer_index].Size();
354 } 358 }
355} 359}
@@ -358,12 +362,14 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons
358 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && 362 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
359 BufferDescriptorB()[buffer_index].Size()}; 363 BufferDescriptorB()[buffer_index].Size()};
360 if (is_buffer_b) { 364 if (is_buffer_b) {
361 ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index, { return 0; }, 365 ASSERT_OR_EXECUTE_MSG(
362 "BufferDescriptorB invalid buffer_index {}", buffer_index); 366 BufferDescriptorB().size() > buffer_index, { return 0; },
367 "BufferDescriptorB invalid buffer_index {}", buffer_index);
363 return BufferDescriptorB()[buffer_index].Size(); 368 return BufferDescriptorB()[buffer_index].Size();
364 } else { 369 } else {
365 ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index, { return 0; }, 370 ASSERT_OR_EXECUTE_MSG(
366 "BufferDescriptorC invalid buffer_index {}", buffer_index); 371 BufferDescriptorC().size() > buffer_index, { return 0; },
372 "BufferDescriptorC invalid buffer_index {}", buffer_index);
367 return BufferDescriptorC()[buffer_index].Size(); 373 return BufferDescriptorC()[buffer_index].Size();
368 } 374 }
369 return 0; 375 return 0;
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index 5d6aac00f..a3fadb533 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(
@@ -852,11 +851,12 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
852 return result; 851 return result;
853 } 852 }
854 853
855 block_manager->UpdateLock(addr, size / PageSize, 854 block_manager->UpdateLock(
856 [](MemoryBlockManager::iterator block, MemoryPermission perm) { 855 addr, size / PageSize,
857 block->ShareToDevice(perm); 856 [](MemoryBlockManager::iterator block, MemoryPermission perm) {
858 }, 857 block->ShareToDevice(perm);
859 perm); 858 },
859 perm);
860 860
861 return RESULT_SUCCESS; 861 return RESULT_SUCCESS;
862} 862}
@@ -874,11 +874,12 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
874 return result; 874 return result;
875 } 875 }
876 876
877 block_manager->UpdateLock(addr, size / PageSize, 877 block_manager->UpdateLock(
878 [](MemoryBlockManager::iterator block, MemoryPermission perm) { 878 addr, size / PageSize,
879 block->UnshareToDevice(perm); 879 [](MemoryBlockManager::iterator block, MemoryPermission perm) {
880 }, 880 block->UnshareToDevice(perm);
881 perm); 881 },
882 perm);
882 883
883 return RESULT_SUCCESS; 884 return RESULT_SUCCESS;
884} 885}
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
665void Scheduler::SwitchContextStep2() { 666void 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
380void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { 380void 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
162class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 169class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 9f30e167d..4157fbf39 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -551,7 +551,8 @@ void WebBrowser::ExecuteShop() {
551} 551}
552 552
553void WebBrowser::ExecuteOffline() { 553void WebBrowser::ExecuteOffline() {
554 frontend.OpenPageLocal(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); 554 frontend.OpenPageLocal(
555 filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
555} 556}
556 557
557} // namespace Service::AM::Applets 558} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index dd80dd1dc..9b4910e53 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -206,7 +206,7 @@ private:
206 AudioCore::StreamPtr stream; 206 AudioCore::StreamPtr stream;
207 std::string device_name; 207 std::string device_name;
208 208
209 [[maybe_unused]] AudoutParams audio_params {}; 209 [[maybe_unused]] AudoutParams audio_params{};
210 210
211 /// This is the event handle used to check if the audio buffer was released 211 /// This is the event handle used to check if the audio buffer was released
212 Kernel::EventPair buffer_event; 212 Kernel::EventPair buffer_event;
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index d29e78d7e..51c2ba964 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -365,8 +365,7 @@ bool Boxcat::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress)
365 365
366 std::thread([this, title, &progress] { 366 std::thread([this, title, &progress] {
367 SynchronizeInternal(applet_manager, dir_getter, title, progress); 367 SynchronizeInternal(applet_manager, dir_getter, title, progress);
368 }) 368 }).detach();
369 .detach();
370 369
371 return true; 370 return true;
372} 371}
@@ -377,8 +376,7 @@ bool Boxcat::SynchronizeDirectory(TitleIDVersion title, std::string name,
377 376
378 std::thread([this, title, name, &progress] { 377 std::thread([this, title, name, &progress] {
379 SynchronizeInternal(applet_manager, dir_getter, title, progress, name); 378 SynchronizeInternal(applet_manager, dir_getter, title, progress, name);
380 }) 379 }).detach();
381 .detach();
382 380
383 return true; 381 return true;
384} 382}
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index ff85cbba6..1ebe949c0 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -86,11 +86,13 @@ public:
86 86
87 [[nodiscard]] s64 GetNextTicks() const; 87 [[nodiscard]] s64 GetNextTicks() const;
88 88
89 [[nodiscard]] std::unique_lock<std::mutex> Lock() const { return std::unique_lock{*guard}; } 89 [[nodiscard]] std::unique_lock<std::mutex> Lock() const {
90 return std::unique_lock{*guard};
91 }
90 92
91 private : 93private:
92 /// Finds the display identified by the specified ID. 94 /// Finds the display identified by the specified ID.
93 [[nodiscard]] VI::Display* FindDisplay(u64 display_id); 95 [[nodiscard]] VI::Display* FindDisplay(u64 display_id);
94 96
95 /// Finds the display identified by the specified ID. 97 /// Finds the display identified by the specified ID.
96 [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; 98 [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
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
26namespace { 26namespace {
27 27
28template <Common::IsBaseOf<AppLoader> T> 28template <Common::DerivedFrom<AppLoader> T>
29std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { 29std::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 b9ea50316..e503118dd 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
211void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) { 220void 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
215void CheatEngine::Reload(std::vector<CheatEntry> cheats) { 227void CheatEngine::Reload(std::vector<CheatEntry> cheats) {
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 2003e096f..5c674a099 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -107,28 +107,21 @@ void Freezer::Unfreeze(VAddr address) {
107 107
108 LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address); 108 LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address);
109 109
110 entries.erase( 110 std::erase_if(entries, [address](const Entry& entry) { return entry.address == address; });
111 std::remove_if(entries.begin(), entries.end(),
112 [&address](const Entry& entry) { return entry.address == address; }),
113 entries.end());
114} 111}
115 112
116bool Freezer::IsFrozen(VAddr address) const { 113bool Freezer::IsFrozen(VAddr address) const {
117 std::lock_guard lock{entries_mutex}; 114 std::lock_guard lock{entries_mutex};
118 115
119 return std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { 116 return FindEntry(address) != entries.cend();
120 return entry.address == address;
121 }) != entries.end();
122} 117}
123 118
124void Freezer::SetFrozenValue(VAddr address, u64 value) { 119void Freezer::SetFrozenValue(VAddr address, u64 value) {
125 std::lock_guard lock{entries_mutex}; 120 std::lock_guard lock{entries_mutex};
126 121
127 const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { 122 const auto iter = FindEntry(address);
128 return entry.address == address;
129 });
130 123
131 if (iter == entries.end()) { 124 if (iter == entries.cend()) {
132 LOG_ERROR(Common_Memory, 125 LOG_ERROR(Common_Memory,
133 "Tried to set freeze value for address={:016X} that is not frozen!", address); 126 "Tried to set freeze value for address={:016X} that is not frozen!", address);
134 return; 127 return;
@@ -143,11 +136,9 @@ void Freezer::SetFrozenValue(VAddr address, u64 value) {
143std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { 136std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const {
144 std::lock_guard lock{entries_mutex}; 137 std::lock_guard lock{entries_mutex};
145 138
146 const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { 139 const auto iter = FindEntry(address);
147 return entry.address == address;
148 });
149 140
150 if (iter == entries.end()) { 141 if (iter == entries.cend()) {
151 return std::nullopt; 142 return std::nullopt;
152 } 143 }
153 144
@@ -160,6 +151,16 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const {
160 return entries; 151 return entries;
161} 152}
162 153
154Freezer::Entries::iterator Freezer::FindEntry(VAddr address) {
155 return std::find_if(entries.begin(), entries.end(),
156 [address](const Entry& entry) { return entry.address == address; });
157}
158
159Freezer::Entries::const_iterator Freezer::FindEntry(VAddr address) const {
160 return std::find_if(entries.begin(), entries.end(),
161 [address](const Entry& entry) { return entry.address == address; });
162}
163
163void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { 164void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
164 if (!IsActive()) { 165 if (!IsActive()) {
165 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); 166 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h
index 2b2326bc4..0fdb701a7 100644
--- a/src/core/tools/freezer.h
+++ b/src/core/tools/freezer.h
@@ -73,13 +73,18 @@ public:
73 std::vector<Entry> GetEntries() const; 73 std::vector<Entry> GetEntries() const;
74 74
75private: 75private:
76 using Entries = std::vector<Entry>;
77
78 Entries::iterator FindEntry(VAddr address);
79 Entries::const_iterator FindEntry(VAddr address) const;
80
76 void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 81 void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
77 void FillEntryReads(); 82 void FillEntryReads();
78 83
79 std::atomic_bool active{false}; 84 std::atomic_bool active{false};
80 85
81 mutable std::mutex entries_mutex; 86 mutable std::mutex entries_mutex;
82 std::vector<Entry> entries; 87 Entries entries;
83 88
84 std::shared_ptr<Core::Timing::EventType> event; 89 std::shared_ptr<Core::Timing::EventType> event;
85 Core::Timing::CoreTiming& core_timing; 90 Core::Timing::CoreTiming& core_timing;
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
149class GCAnalog final : public Input::AnalogDevice { 149class GCAnalog final : public Input::AnalogDevice {
150public: 150public:
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
241void GCAnalogFactory::BeginConfiguration() { 241void 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
330class SDLAnalog final : public Input::AnalogDevice { 330class SDLAnalog final : public Input::AnalogDevice {
331public: 331public:
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
470private: 473private:
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 6c95a8b42..3f4eaf448 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -224,8 +224,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
224 } else { 224 } else {
225 failure_callback(); 225 failure_callback();
226 } 226 }
227 }) 227 }).detach();
228 .detach();
229} 228}
230 229
231CalibrationConfigurationJob::CalibrationConfigurationJob( 230CalibrationConfigurationJob::CalibrationConfigurationJob(
@@ -279,8 +278,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
279 complete_event.Wait(); 278 complete_event.Wait();
280 socket.Stop(); 279 socket.Stop();
281 worker_thread.join(); 280 worker_thread.join();
282 }) 281 }).detach();
283 .detach();
284} 282}
285 283
286CalibrationConfigurationJob::~CalibrationConfigurationJob() { 284CalibrationConfigurationJob::~CalibrationConfigurationJob() {
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index be71e1733..eb49a36bf 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -403,7 +403,7 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
403 } 403 }
404 }; 404 };
405 405
406 const auto num_workers{static_cast<std::size_t>(std::thread::hardware_concurrency() + 1ULL)}; 406 const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())};
407 const std::size_t bucket_size{transferable->size() / num_workers}; 407 const std::size_t bucket_size{transferable->size() / num_workers};
408 std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers); 408 std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers);
409 std::vector<std::thread> threads(num_workers); 409 std::vector<std::thread> threads(num_workers);
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h
index 71daac9d7..31885ef42 100644
--- a/src/video_core/renderer_vulkan/wrapper.h
+++ b/src/video_core/renderer_vulkan/wrapper.h
@@ -756,8 +756,8 @@ public:
756 } 756 }
757 757
758 VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size, 758 VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
759 void* data, VkDeviceSize stride, VkQueryResultFlags flags) const 759 void* data, VkDeviceSize stride,
760 noexcept { 760 VkQueryResultFlags flags) const noexcept {
761 return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride, 761 return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride,
762 flags); 762 flags);
763 } 763 }
@@ -849,8 +849,8 @@ public:
849 dld->vkCmdBindPipeline(handle, bind_point, pipeline); 849 dld->vkCmdBindPipeline(handle, bind_point, pipeline);
850 } 850 }
851 851
852 void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType index_type) const 852 void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset,
853 noexcept { 853 VkIndexType index_type) const noexcept {
854 dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type); 854 dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type);
855 } 855 }
856 856
@@ -863,8 +863,8 @@ public:
863 BindVertexBuffers(binding, 1, &buffer, &offset); 863 BindVertexBuffers(binding, 1, &buffer, &offset);
864 } 864 }
865 865
866 void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex, u32 first_instance) const 866 void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex,
867 noexcept { 867 u32 first_instance) const noexcept {
868 dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance); 868 dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance);
869 } 869 }
870 870
@@ -874,15 +874,15 @@ public:
874 first_instance); 874 first_instance);
875 } 875 }
876 876
877 void ClearAttachments(Span<VkClearAttachment> attachments, Span<VkClearRect> rects) const 877 void ClearAttachments(Span<VkClearAttachment> attachments,
878 noexcept { 878 Span<VkClearRect> rects) const noexcept {
879 dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(), 879 dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
880 rects.data()); 880 rects.data());
881 } 881 }
882 882
883 void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, 883 void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
884 VkImageLayout dst_layout, Span<VkImageBlit> regions, VkFilter filter) const 884 VkImageLayout dst_layout, Span<VkImageBlit> regions,
885 noexcept { 885 VkFilter filter) const noexcept {
886 dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), 886 dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
887 regions.data(), filter); 887 regions.data(), filter);
888 } 888 }
@@ -907,8 +907,8 @@ public:
907 regions.data()); 907 regions.data());
908 } 908 }
909 909
910 void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, Span<VkBufferCopy> regions) const 910 void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
911 noexcept { 911 Span<VkBufferCopy> regions) const noexcept {
912 dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data()); 912 dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data());
913 } 913 }
914 914
@@ -924,8 +924,8 @@ public:
924 regions.data()); 924 regions.data());
925 } 925 }
926 926
927 void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size, u32 data) const 927 void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size,
928 noexcept { 928 u32 data) const noexcept {
929 dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data); 929 dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data);
930 } 930 }
931 931
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 8d86020f6..336397cdb 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -187,24 +187,26 @@ std::optional<std::pair<BufferInfo, u64>> TrackLDC(const CFGRebuildState& state,
187 187
188std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos, 188std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos,
189 u64 ldc_tracked_register) { 189 u64 ldc_tracked_register) {
190 return TrackInstruction<u64>(state, pos, 190 return TrackInstruction<u64>(
191 [ldc_tracked_register](auto instr, const auto& opcode) { 191 state, pos,
192 return opcode.GetId() == OpCode::Id::SHL_IMM && 192 [ldc_tracked_register](auto instr, const auto& opcode) {
193 instr.gpr0.Value() == ldc_tracked_register; 193 return opcode.GetId() == OpCode::Id::SHL_IMM &&
194 }, 194 instr.gpr0.Value() == ldc_tracked_register;
195 [](auto instr, const auto&) { return instr.gpr8.Value(); }); 195 },
196 [](auto instr, const auto&) { return instr.gpr8.Value(); });
196} 197}
197 198
198std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos, 199std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos,
199 u64 shl_tracked_register) { 200 u64 shl_tracked_register) {
200 return TrackInstruction<u32>(state, pos, 201 return TrackInstruction<u32>(
201 [shl_tracked_register](auto instr, const auto& opcode) { 202 state, pos,
202 return opcode.GetId() == OpCode::Id::IMNMX_IMM && 203 [shl_tracked_register](auto instr, const auto& opcode) {
203 instr.gpr0.Value() == shl_tracked_register; 204 return opcode.GetId() == OpCode::Id::IMNMX_IMM &&
204 }, 205 instr.gpr0.Value() == shl_tracked_register;
205 [](auto instr, const auto&) { 206 },
206 return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1); 207 [](auto instr, const auto&) {
207 }); 208 return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1);
209 });
208} 210}
209 211
210std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) { 212std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) {
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 63adbc4a3..e4739394d 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -471,9 +471,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock&
471 471
472 const auto [base_address, index, offset] = 472 const auto [base_address, index, offset] =
473 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); 473 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
474 ASSERT_OR_EXECUTE_MSG(base_address != nullptr, 474 ASSERT_OR_EXECUTE_MSG(
475 { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, 475 base_address != nullptr, { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
476 "Global memory tracking failed"); 476 "Global memory tracking failed");
477 477
478 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); 478 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
479 479
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/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index b1850bc95..597defe8c 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -281,24 +281,25 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
281 281
282 button->setContextMenuPolicy(Qt::CustomContextMenu); 282 button->setContextMenuPolicy(Qt::CustomContextMenu);
283 connect(button, &QPushButton::clicked, [=, this] { 283 connect(button, &QPushButton::clicked, [=, this] {
284 HandleClick(button_map[button_id], 284 HandleClick(
285 [=, this](Common::ParamPackage params) { 285 button_map[button_id],
286 // Workaround for ZL & ZR for analog triggers like on XBOX controllors. 286 [=, this](Common::ParamPackage params) {
287 // Analog triggers (from controllers like the XBOX controller) would not 287 // Workaround for ZL & ZR for analog triggers like on XBOX controllors.
288 // work due to a different range of their signals (from 0 to 255 on 288 // Analog triggers (from controllers like the XBOX controller) would not
289 // analog triggers instead of -32768 to 32768 on analog joysticks). The 289 // work due to a different range of their signals (from 0 to 255 on
290 // SDL driver misinterprets analog triggers as analog joysticks. 290 // analog triggers instead of -32768 to 32768 on analog joysticks). The
291 // TODO: reinterpret the signal range for analog triggers to map the 291 // SDL driver misinterprets analog triggers as analog joysticks.
292 // values correctly. This is required for the correct emulation of the 292 // TODO: reinterpret the signal range for analog triggers to map the
293 // analog triggers of the GameCube controller. 293 // values correctly. This is required for the correct emulation of the
294 if (button_id == Settings::NativeButton::ZL || 294 // analog triggers of the GameCube controller.
295 button_id == Settings::NativeButton::ZR) { 295 if (button_id == Settings::NativeButton::ZL ||
296 params.Set("direction", "+"); 296 button_id == Settings::NativeButton::ZR) {
297 params.Set("threshold", "0.5"); 297 params.Set("direction", "+");
298 } 298 params.Set("threshold", "0.5");
299 buttons_param[button_id] = std::move(params); 299 }
300 }, 300 buttons_param[button_id] = std::move(params);
301 InputCommon::Polling::DeviceType::Button); 301 },
302 InputCommon::Polling::DeviceType::Button);
302 }); 303 });
303 connect(button, &QPushButton::customContextMenuRequested, 304 connect(button, &QPushButton::customContextMenuRequested,
304 [=, this](const QPoint& menu_location) { 305 [=, this](const QPoint& menu_location) {
@@ -325,12 +326,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
325 326
326 analog_button->setContextMenuPolicy(Qt::CustomContextMenu); 327 analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
327 connect(analog_button, &QPushButton::clicked, [=, this] { 328 connect(analog_button, &QPushButton::clicked, [=, this] {
328 HandleClick(analog_map_buttons[analog_id][sub_button_id], 329 HandleClick(
329 [=, this](const Common::ParamPackage& params) { 330 analog_map_buttons[analog_id][sub_button_id],
330 SetAnalogButton(params, analogs_param[analog_id], 331 [=, this](const Common::ParamPackage& params) {
331 analog_sub_buttons[sub_button_id]); 332 SetAnalogButton(params, analogs_param[analog_id],
332 }, 333 analog_sub_buttons[sub_button_id]);
333 InputCommon::Polling::DeviceType::Button); 334 },
335 InputCommon::Polling::DeviceType::Button);
334 }); 336 });
335 connect(analog_button, &QPushButton::customContextMenuRequested, 337 connect(analog_button, &QPushButton::customContextMenuRequested,
336 [=, this](const QPoint& menu_location) { 338 [=, this](const QPoint& menu_location) {
@@ -357,11 +359,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
357 tr("After pressing OK, first move your joystick horizontally, " 359 tr("After pressing OK, first move your joystick horizontally, "
358 "and then vertically."), 360 "and then vertically."),
359 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { 361 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
360 HandleClick(analog_map_stick[analog_id], 362 HandleClick(
361 [=, this](const Common::ParamPackage& params) { 363 analog_map_stick[analog_id],
362 analogs_param[analog_id] = params; 364 [=, this](const Common::ParamPackage& params) {
363 }, 365 analogs_param[analog_id] = params;
364 InputCommon::Polling::DeviceType::Analog); 366 },
367 InputCommon::Polling::DeviceType::Analog);
365 } 368 }
366 }); 369 });
367 370
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index ea2549363..5bcf5ffa8 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -84,11 +84,12 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent)
84 84
85 button->setContextMenuPolicy(Qt::CustomContextMenu); 85 button->setContextMenuPolicy(Qt::CustomContextMenu);
86 connect(button, &QPushButton::clicked, [=, this] { 86 connect(button, &QPushButton::clicked, [=, this] {
87 HandleClick(button_map[button_id], 87 HandleClick(
88 [=, this](const Common::ParamPackage& params) { 88 button_map[button_id],
89 buttons_param[button_id] = params; 89 [=, this](const Common::ParamPackage& params) {
90 }, 90 buttons_param[button_id] = params;
91 InputCommon::Polling::DeviceType::Button); 91 },
92 InputCommon::Polling::DeviceType::Button);
92 }); 93 });
93 connect(button, &QPushButton::customContextMenuRequested, 94 connect(button, &QPushButton::customContextMenuRequested,
94 [=, this](const QPoint& menu_location) { 95 [=, this](const QPoint& menu_location) {
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
351void GameListWorker::run() { 351void 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(),