summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/alignment.h47
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/constants.h1
-rw-r--r--src/core/cpu_manager.h10
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.cpp4
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.h2
-rw-r--r--src/core/file_sys/registered_cache.cpp98
-rw-r--r--src/core/file_sys/registered_cache.h4
-rw-r--r--src/core/file_sys/vfs_concat.cpp8
-rw-r--r--src/core/file_sys/vfs_concat.h6
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp1
-rw-r--r--src/core/hle/kernel/handle_table.cpp8
-rw-r--r--src/core/hle/kernel/handle_table.h7
-rw-r--r--src/core/hle/kernel/kernel.cpp16
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/memory/address_space_info.cpp67
-rw-r--r--src/core/hle/kernel/memory/address_space_info.h29
-rw-r--r--src/core/hle/kernel/memory/memory_layout.h2
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/process.h12
-rw-r--r--src/core/hle/kernel/scheduler.cpp2
-rw-r--r--src/core/hle/kernel/svc.cpp7
-rw-r--r--src/core/hle/kernel/synchronization.cpp1
-rw-r--r--src/core/hle/kernel/thread.cpp24
-rw-r--r--src/core/hle/kernel/thread.h7
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp4
-rw-r--r--src/core/hle/service/mii/manager.cpp484
-rw-r--r--src/core/hle/service/mii/manager.h331
-rw-r--r--src/core/hle/service/mii/mii.cpp315
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp420
-rw-r--r--src/core/hle/service/mii/mii_manager.h273
-rw-r--r--src/core/hle/service/mii/raw_data.cpp2261
-rw-r--r--src/core/hle/service/mii/raw_data.h27
-rw-r--r--src/core/hle/service/mii/types.h67
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp29
-rw-r--r--src/core/memory/dmnt_cheat_vm.h14
-rw-r--r--src/core/settings.cpp84
-rw-r--r--src/core/settings.h4
-rw-r--r--src/core/telemetry_session.cpp2
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp69
-rw-r--r--src/input_common/gcadapter/gc_adapter.h10
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp24
-rw-r--r--src/video_core/CMakeLists.txt4
-rw-r--r--src/video_core/gpu.cpp2
-rw-r--r--src/video_core/gpu.h11
-rw-r--r--src/video_core/macro/macro.h3
-rw-r--r--src/video_core/macro/macro_hle.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp24
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h10
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp181
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h36
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp718
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp63
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp194
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp131
-rw-r--r--src/video_core/renderer_vulkan/vk_descriptor_pool.cpp33
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp272
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp423
-rw-r--r--src/video_core/renderer_vulkan/vk_image.cpp38
-rw-r--r--src/video_core/renderer_vulkan/vk_memory_manager.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp66
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp16
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp88
-rw-r--r--src/video_core/renderer_vulkan/vk_renderpass_cache.cpp129
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp29
-rw-r--r--src/video_core/renderer_vulkan/vk_sampler_cache.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp57
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_util.cpp14
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp25
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_stream_buffer.cpp35
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp94
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp241
-rw-r--r--src/video_core/renderer_vulkan/wrapper.cpp120
-rw-r--r--src/video_core/shader/async_shaders.cpp181
-rw-r--r--src/video_core/shader/async_shaders.h109
-rw-r--r--src/video_core/shader_cache.h4
-rw-r--r--src/video_core/shader_notify.cpp42
-rw-r--r--src/video_core/shader_notify.h29
-rw-r--r--src/yuzu/configuration/config.cpp6
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp22
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui10
-rw-r--r--src/yuzu/main.cpp58
-rw-r--r--src/yuzu/main.h1
-rw-r--r--src/yuzu_cmd/config.cpp4
-rw-r--r--src/yuzu_cmd/default_ini.h4
89 files changed, 5836 insertions, 2581 deletions
diff --git a/src/common/alignment.h b/src/common/alignment.h
index b37044bb6..4025ba651 100644
--- a/src/common/alignment.h
+++ b/src/common/alignment.h
@@ -3,7 +3,6 @@
3#pragma once 3#pragma once
4 4
5#include <cstddef> 5#include <cstddef>
6#include <memory>
7#include <type_traits> 6#include <type_traits>
8 7
9namespace Common { 8namespace Common {
@@ -54,66 +53,28 @@ public:
54 using size_type = std::size_t; 53 using size_type = std::size_t;
55 using difference_type = std::ptrdiff_t; 54 using difference_type = std::ptrdiff_t;
56 55
57 using pointer = T*;
58 using const_pointer = const T*;
59
60 using reference = T&;
61 using const_reference = const T&;
62
63 using propagate_on_container_copy_assignment = std::true_type; 56 using propagate_on_container_copy_assignment = std::true_type;
64 using propagate_on_container_move_assignment = std::true_type; 57 using propagate_on_container_move_assignment = std::true_type;
65 using propagate_on_container_swap = std::true_type; 58 using propagate_on_container_swap = std::true_type;
66 using is_always_equal = std::true_type; 59 using is_always_equal = std::true_type;
67 60
68public:
69 constexpr AlignmentAllocator() noexcept = default; 61 constexpr AlignmentAllocator() noexcept = default;
70 62
71 template <typename T2> 63 template <typename T2>
72 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} 64 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
73 65
74 pointer address(reference r) noexcept { 66 T* allocate(size_type n) {
75 return std::addressof(r); 67 return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
76 }
77
78 const_pointer address(const_reference r) const noexcept {
79 return std::addressof(r);
80 }
81
82 pointer allocate(size_type n) {
83 return static_cast<pointer>(::operator new (n, std::align_val_t{Align}));
84 }
85
86 void deallocate(pointer p, size_type) {
87 ::operator delete (p, std::align_val_t{Align});
88 } 68 }
89 69
90 void construct(pointer p, const value_type& wert) { 70 void deallocate(T* p, size_type n) {
91 new (p) value_type(wert); 71 ::operator delete (p, n * sizeof(T), std::align_val_t{Align});
92 }
93
94 void destroy(pointer p) {
95 p->~value_type();
96 }
97
98 size_type max_size() const noexcept {
99 return size_type(-1) / sizeof(value_type);
100 } 72 }
101 73
102 template <typename T2> 74 template <typename T2>
103 struct rebind { 75 struct rebind {
104 using other = AlignmentAllocator<T2, Align>; 76 using other = AlignmentAllocator<T2, Align>;
105 }; 77 };
106
107 bool operator!=(const AlignmentAllocator<T, Align>& other) const noexcept {
108 return !(*this == other);
109 }
110
111 // Returns true if and only if storage allocated from *this
112 // can be deallocated from other, and vice versa.
113 // Always returns true for stateless allocators.
114 bool operator==(const AlignmentAllocator<T, Align>& other) const noexcept {
115 return true;
116 }
117}; 78};
118 79
119} // namespace Common 80} // namespace Common
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d1f173f42..c42f95705 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -185,6 +185,7 @@ add_library(core STATIC
185 hle/kernel/object.h 185 hle/kernel/object.h
186 hle/kernel/physical_core.cpp 186 hle/kernel/physical_core.cpp
187 hle/kernel/physical_core.h 187 hle/kernel/physical_core.h
188 hle/kernel/physical_memory.h
188 hle/kernel/process.cpp 189 hle/kernel/process.cpp
189 hle/kernel/process.h 190 hle/kernel/process.h
190 hle/kernel/process_capability.cpp 191 hle/kernel/process_capability.cpp
@@ -398,10 +399,13 @@ add_library(core STATIC
398 hle/service/lm/manager.h 399 hle/service/lm/manager.h
399 hle/service/mig/mig.cpp 400 hle/service/mig/mig.cpp
400 hle/service/mig/mig.h 401 hle/service/mig/mig.h
402 hle/service/mii/manager.cpp
403 hle/service/mii/manager.h
401 hle/service/mii/mii.cpp 404 hle/service/mii/mii.cpp
402 hle/service/mii/mii.h 405 hle/service/mii/mii.h
403 hle/service/mii/mii_manager.cpp 406 hle/service/mii/raw_data.cpp
404 hle/service/mii/mii_manager.h 407 hle/service/mii/raw_data.h
408 hle/service/mii/types.h
405 hle/service/mm/mm_u.cpp 409 hle/service/mm/mm_u.cpp
406 hle/service/mm/mm_u.h 410 hle/service/mm/mm_u.h
407 hle/service/ncm/ncm.cpp 411 hle/service/ncm/ncm.cpp
diff --git a/src/core/constants.h b/src/core/constants.h
index 6d0ec022a..81c5cb279 100644
--- a/src/core/constants.h
+++ b/src/core/constants.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include "common/common_types.h" 8#include "common/common_types.h"
8 9
9// This is to consolidate system-wide constants that are used by multiple components of yuzu. 10// This is to consolidate system-wide constants that are used by multiple components of yuzu.
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index 35929ed94..17420c941 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -9,6 +9,9 @@
9#include <functional> 9#include <functional>
10#include <memory> 10#include <memory>
11#include <thread> 11#include <thread>
12
13#include "common/fiber.h"
14#include "common/thread.h"
12#include "core/hardware_properties.h" 15#include "core/hardware_properties.h"
13 16
14namespace Common { 17namespace Common {
@@ -46,9 +49,9 @@ public:
46 49
47 void Pause(bool paused); 50 void Pause(bool paused);
48 51
49 std::function<void(void*)> GetGuestThreadStartFunc(); 52 static std::function<void(void*)> GetGuestThreadStartFunc();
50 std::function<void(void*)> GetIdleThreadStartFunc(); 53 static std::function<void(void*)> GetIdleThreadStartFunc();
51 std::function<void(void*)> GetSuspendThreadStartFunc(); 54 static std::function<void(void*)> GetSuspendThreadStartFunc();
52 void* GetStartFuncParamater(); 55 void* GetStartFuncParamater();
53 56
54 void PreemptSingleCore(bool from_running_enviroment = true); 57 void PreemptSingleCore(bool from_running_enviroment = true);
@@ -97,7 +100,6 @@ private:
97 bool is_async_gpu{}; 100 bool is_async_gpu{};
98 bool is_multicore{}; 101 bool is_multicore{};
99 std::atomic<std::size_t> current_core{}; 102 std::atomic<std::size_t> current_core{};
100 std::size_t preemption_count{};
101 std::size_t idle_count{}; 103 std::size_t idle_count{};
102 static constexpr std::size_t max_cycle_runs = 5; 104 static constexpr std::size_t max_cycle_runs = 5;
103 105
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp
index d126ae8dd..2aff2708a 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.cpp
+++ b/src/core/file_sys/fsmitm_romfsbuild.cpp
@@ -240,7 +240,7 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_)
240 240
241RomFSBuildContext::~RomFSBuildContext() = default; 241RomFSBuildContext::~RomFSBuildContext() = default;
242 242
243std::map<u64, VirtualFile> RomFSBuildContext::Build() { 243std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
244 const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs); 244 const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs);
245 const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files); 245 const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files);
246 dir_hash_table_size = 4 * dir_hash_table_entry_count; 246 dir_hash_table_size = 4 * dir_hash_table_entry_count;
@@ -294,7 +294,7 @@ std::map<u64, VirtualFile> RomFSBuildContext::Build() {
294 cur_dir->parent->child = cur_dir; 294 cur_dir->parent->child = cur_dir;
295 } 295 }
296 296
297 std::map<u64, VirtualFile> out; 297 std::multimap<u64, VirtualFile> out;
298 298
299 // Populate file tables. 299 // Populate file tables.
300 for (const auto& it : files) { 300 for (const auto& it : files) {
diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h
index a62502193..049de180b 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.h
+++ b/src/core/file_sys/fsmitm_romfsbuild.h
@@ -43,7 +43,7 @@ public:
43 ~RomFSBuildContext(); 43 ~RomFSBuildContext();
44 44
45 // This finalizes the context. 45 // This finalizes the context.
46 std::map<u64, VirtualFile> Build(); 46 std::multimap<u64, VirtualFile> Build();
47 47
48private: 48private:
49 VirtualDir base; 49 VirtualDir base;
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 27c1b0233..37351c561 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -547,6 +547,56 @@ InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_ex
547 return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy); 547 return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
548} 548}
549 549
550bool RegisteredCache::RemoveExistingEntry(u64 title_id) {
551 const auto delete_nca = [this](const NcaID& id) {
552 const auto path = GetRelativePathFromNcaID(id, false, true, false);
553
554 if (dir->GetFileRelative(path) == nullptr) {
555 return false;
556 }
557
558 Core::Crypto::SHA256Hash hash{};
559 mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0);
560 const auto dirname = fmt::format("000000{:02X}", hash[0]);
561
562 const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
563
564 const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexToString(id, false)));
565
566 return res;
567 };
568
569 // If an entry exists in the registered cache, remove it
570 if (HasEntry(title_id, ContentRecordType::Meta)) {
571 LOG_INFO(Loader,
572 "Previously installed entry (v{}) for title_id={:016X} detected! "
573 "Attempting to remove...",
574 GetEntryVersion(title_id).value_or(0), title_id);
575 // Get all the ncas associated with the current CNMT and delete them
576 const auto meta_old_id =
577 GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
578 const auto program_id =
579 GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
580 const auto data_id =
581 GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
582 const auto control_id =
583 GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
584 const auto html_id =
585 GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
586 const auto legal_id =
587 GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
588
589 delete_nca(meta_old_id);
590 delete_nca(program_id);
591 delete_nca(data_id);
592 delete_nca(control_id);
593 delete_nca(html_id);
594 delete_nca(legal_id);
595 return true;
596 }
597 return false;
598}
599
550InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists, 600InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
551 const VfsCopyFunction& copy) { 601 const VfsCopyFunction& copy) {
552 const auto ncas = nsp.GetNCAsCollapsed(); 602 const auto ncas = nsp.GetNCAsCollapsed();
@@ -560,31 +610,57 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
560 return InstallResult::ErrorMetaFailed; 610 return InstallResult::ErrorMetaFailed;
561 } 611 }
562 612
563 // Install Metadata File
564 const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32); 613 const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32);
565 const auto meta_id = Common::HexStringToArray<16>(meta_id_raw); 614 const auto meta_id = Common::HexStringToArray<16>(meta_id_raw);
566 615
567 const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id); 616 if ((*meta_iter)->GetSubdirectories().empty()) {
568 if (res != InstallResult::Success) 617 LOG_ERROR(Loader,
569 return res; 618 "The file you are attempting to install does not contain a section0 within the "
619 "metadata NCA and is therefore malformed. Verify that the file is valid.");
620 return InstallResult::ErrorMetaFailed;
621 }
570 622
571 // Install all the other NCAs
572 const auto section0 = (*meta_iter)->GetSubdirectories()[0]; 623 const auto section0 = (*meta_iter)->GetSubdirectories()[0];
624
625 if (section0->GetFiles().empty()) {
626 LOG_ERROR(Loader,
627 "The file you are attempting to install does not contain a CNMT within the "
628 "metadata NCA and is therefore malformed. Verify that the file is valid.");
629 return InstallResult::ErrorMetaFailed;
630 }
631
573 const auto cnmt_file = section0->GetFiles()[0]; 632 const auto cnmt_file = section0->GetFiles()[0];
574 const CNMT cnmt(cnmt_file); 633 const CNMT cnmt(cnmt_file);
634
635 const auto title_id = cnmt.GetTitleID();
636 const auto result = RemoveExistingEntry(title_id);
637
638 // Install Metadata File
639 const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id);
640 if (res != InstallResult::Success) {
641 return res;
642 }
643
644 // Install all the other NCAs
575 for (const auto& record : cnmt.GetContentRecords()) { 645 for (const auto& record : cnmt.GetContentRecords()) {
576 // Ignore DeltaFragments, they are not useful to us 646 // Ignore DeltaFragments, they are not useful to us
577 if (record.type == ContentRecordType::DeltaFragment) 647 if (record.type == ContentRecordType::DeltaFragment) {
578 continue; 648 continue;
649 }
579 const auto nca = GetNCAFromNSPForID(nsp, record.nca_id); 650 const auto nca = GetNCAFromNSPForID(nsp, record.nca_id);
580 if (nca == nullptr) 651 if (nca == nullptr) {
581 return InstallResult::ErrorCopyFailed; 652 return InstallResult::ErrorCopyFailed;
653 }
582 const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); 654 const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id);
583 if (res2 != InstallResult::Success) 655 if (res2 != InstallResult::Success) {
584 return res2; 656 return res2;
657 }
585 } 658 }
586 659
587 Refresh(); 660 Refresh();
661 if (result) {
662 return InstallResult::OverwriteExisting;
663 }
588 return InstallResult::Success; 664 return InstallResult::Success;
589} 665}
590 666
@@ -610,8 +686,9 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
610 mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); 686 mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0);
611 memcpy(&c_rec.nca_id, &c_rec.hash, 16); 687 memcpy(&c_rec.nca_id, &c_rec.hash, 16);
612 const CNMT new_cnmt(header, opt_header, {c_rec}, {}); 688 const CNMT new_cnmt(header, opt_header, {c_rec}, {});
613 if (!RawInstallYuzuMeta(new_cnmt)) 689 if (!RawInstallYuzuMeta(new_cnmt)) {
614 return InstallResult::ErrorMetaFailed; 690 return InstallResult::ErrorMetaFailed;
691 }
615 return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); 692 return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
616} 693}
617 694
@@ -649,8 +726,9 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti
649 } 726 }
650 727
651 auto out = dir->CreateFileRelative(path); 728 auto out = dir->CreateFileRelative(path);
652 if (out == nullptr) 729 if (out == nullptr) {
653 return InstallResult::ErrorCopyFailed; 730 return InstallResult::ErrorCopyFailed;
731 }
654 return copy(in, out, VFS_RC_LARGE_COPY_BLOCK) ? InstallResult::Success 732 return copy(in, out, VFS_RC_LARGE_COPY_BLOCK) ? InstallResult::Success
655 : InstallResult::ErrorCopyFailed; 733 : InstallResult::ErrorCopyFailed;
656} 734}
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index f339cd17b..29cf0d40c 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -34,6 +34,7 @@ using VfsCopyFunction = std::function<bool(const VirtualFile&, const VirtualFile
34 34
35enum class InstallResult { 35enum class InstallResult {
36 Success, 36 Success,
37 OverwriteExisting,
37 ErrorAlreadyExists, 38 ErrorAlreadyExists,
38 ErrorCopyFailed, 39 ErrorCopyFailed,
39 ErrorMetaFailed, 40 ErrorMetaFailed,
@@ -154,6 +155,9 @@ public:
154 std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {}, 155 std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
155 std::optional<u64> title_id = {}) const override; 156 std::optional<u64> title_id = {}) const override;
156 157
158 // Removes an existing entry based on title id
159 bool RemoveExistingEntry(u64 title_id);
160
157 // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure 161 // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
158 // there is a meta NCA and all of them are accessible. 162 // there is a meta NCA and all of them are accessible.
159 InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false, 163 InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 16d801c0c..e0ff70174 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -11,7 +11,7 @@
11 11
12namespace FileSys { 12namespace FileSys {
13 13
14static bool VerifyConcatenationMapContinuity(const std::map<u64, VirtualFile>& map) { 14static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFile>& map) {
15 const auto last_valid = --map.end(); 15 const auto last_valid = --map.end();
16 for (auto iter = map.begin(); iter != last_valid;) { 16 for (auto iter = map.begin(); iter != last_valid;) {
17 const auto old = iter++; 17 const auto old = iter++;
@@ -27,12 +27,12 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::s
27 : name(std::move(name)) { 27 : name(std::move(name)) {
28 std::size_t next_offset = 0; 28 std::size_t next_offset = 0;
29 for (const auto& file : files_) { 29 for (const auto& file : files_) {
30 files[next_offset] = file; 30 files.emplace(next_offset, file);
31 next_offset += file->GetSize(); 31 next_offset += file->GetSize();
32 } 32 }
33} 33}
34 34
35ConcatenatedVfsFile::ConcatenatedVfsFile(std::map<u64, VirtualFile> files_, std::string name) 35ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name)
36 : files(std::move(files_)), name(std::move(name)) { 36 : files(std::move(files_)), name(std::move(name)) {
37 ASSERT(VerifyConcatenationMapContinuity(files)); 37 ASSERT(VerifyConcatenationMapContinuity(files));
38} 38}
@@ -50,7 +50,7 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector<VirtualFile> f
50} 50}
51 51
52VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, 52VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
53 std::map<u64, VirtualFile> files, 53 std::multimap<u64, VirtualFile> files,
54 std::string name) { 54 std::string name) {
55 if (files.empty()) 55 if (files.empty())
56 return nullptr; 56 return nullptr;
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h
index c90f9d5d1..7a26343c0 100644
--- a/src/core/file_sys/vfs_concat.h
+++ b/src/core/file_sys/vfs_concat.h
@@ -15,7 +15,7 @@ namespace FileSys {
15// read-only. 15// read-only.
16class ConcatenatedVfsFile : public VfsFile { 16class ConcatenatedVfsFile : public VfsFile {
17 ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); 17 ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name);
18 ConcatenatedVfsFile(std::map<u64, VirtualFile> files, std::string name); 18 ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name);
19 19
20public: 20public:
21 ~ConcatenatedVfsFile() override; 21 ~ConcatenatedVfsFile() override;
@@ -25,7 +25,7 @@ public:
25 25
26 /// Convenience function that turns a map of offsets to files into a concatenated file, filling 26 /// Convenience function that turns a map of offsets to files into a concatenated file, filling
27 /// gaps with a given filler byte. 27 /// gaps with a given filler byte.
28 static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::map<u64, VirtualFile> files, 28 static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::multimap<u64, VirtualFile> files,
29 std::string name); 29 std::string name);
30 30
31 std::string GetName() const override; 31 std::string GetName() const override;
@@ -40,7 +40,7 @@ public:
40 40
41private: 41private:
42 // Maps starting offset to file -- more efficient. 42 // Maps starting offset to file -- more efficient.
43 std::map<u64, VirtualFile> files; 43 std::multimap<u64, VirtualFile> files;
44 std::string name; 44 std::string name;
45}; 45};
46 46
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 4d2a9b35d..df0debe1b 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -24,7 +24,6 @@ namespace Kernel {
24// Wake up num_to_wake (or all) threads in a vector. 24// Wake up num_to_wake (or all) threads in a vector.
25void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, 25void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads,
26 s32 num_to_wake) { 26 s32 num_to_wake) {
27 auto& time_manager = system.Kernel().TimeManager();
28 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process 27 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process
29 // them all. 28 // them all.
30 std::size_t last = waiting_threads.size(); 29 std::size_t last = waiting_threads.size();
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 35448b576..fb30b6f8b 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -8,7 +8,9 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/errors.h" 9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/handle_table.h" 10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/scheduler.h"
12#include "core/hle/kernel/thread.h" 14#include "core/hle/kernel/thread.h"
13 15
14namespace Kernel { 16namespace Kernel {
@@ -22,7 +24,7 @@ constexpr u16 GetGeneration(Handle handle) {
22} 24}
23} // Anonymous namespace 25} // Anonymous namespace
24 26
25HandleTable::HandleTable() { 27HandleTable::HandleTable(KernelCore& kernel) : kernel{kernel} {
26 Clear(); 28 Clear();
27} 29}
28 30
@@ -103,9 +105,9 @@ bool HandleTable::IsValid(Handle handle) const {
103 105
104std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const { 106std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
105 if (handle == CurrentThread) { 107 if (handle == CurrentThread) {
106 return SharedFrom(GetCurrentThread()); 108 return SharedFrom(kernel.CurrentScheduler().GetCurrentThread());
107 } else if (handle == CurrentProcess) { 109 } else if (handle == CurrentProcess) {
108 return SharedFrom(Core::System::GetInstance().CurrentProcess()); 110 return SharedFrom(kernel.CurrentProcess());
109 } 111 }
110 112
111 if (!IsValid(handle)) { 113 if (!IsValid(handle)) {
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index 8029660ed..c9dab8cdd 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -14,6 +14,8 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17class KernelCore;
18
17enum KernelHandle : Handle { 19enum KernelHandle : Handle {
18 InvalidHandle = 0, 20 InvalidHandle = 0,
19 CurrentThread = 0xFFFF8000, 21 CurrentThread = 0xFFFF8000,
@@ -48,7 +50,7 @@ public:
48 /// This is the maximum limit of handles allowed per process in Horizon 50 /// This is the maximum limit of handles allowed per process in Horizon
49 static constexpr std::size_t MAX_COUNT = 1024; 51 static constexpr std::size_t MAX_COUNT = 1024;
50 52
51 HandleTable(); 53 explicit HandleTable(KernelCore& kernel);
52 ~HandleTable(); 54 ~HandleTable();
53 55
54 /** 56 /**
@@ -134,6 +136,9 @@ private:
134 136
135 /// Head of the free slots linked list. 137 /// Head of the free slots linked list.
136 u16 next_free_slot = 0; 138 u16 next_free_slot = 0;
139
140 /// Underlying kernel instance that this handle table operates under.
141 KernelCore& kernel;
137}; 142};
138 143
139} // namespace Kernel 144} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 22fc34b10..8dd4a2637 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -50,7 +50,8 @@ namespace Kernel {
50 50
51struct KernelCore::Impl { 51struct KernelCore::Impl {
52 explicit Impl(Core::System& system, KernelCore& kernel) 52 explicit Impl(Core::System& system, KernelCore& kernel)
53 : global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {} 53 : global_scheduler{kernel}, synchronization{system}, time_manager{system},
54 global_handle_table{kernel}, system{system} {}
54 55
55 void SetMulticore(bool is_multicore) { 56 void SetMulticore(bool is_multicore) {
56 this->is_multicore = is_multicore; 57 this->is_multicore = is_multicore;
@@ -162,13 +163,14 @@ struct KernelCore::Impl {
162 void InitializeSuspendThreads() { 163 void InitializeSuspendThreads() {
163 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 164 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
164 std::string name = "Suspend Thread Id:" + std::to_string(i); 165 std::string name = "Suspend Thread Id:" + std::to_string(i);
165 std::function<void(void*)> init_func = 166 std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
166 system.GetCpuManager().GetSuspendThreadStartFunc();
167 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 167 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
168 ThreadType type = 168 const auto type =
169 static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND); 169 static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
170 auto thread_res = Thread::Create(system, type, name, 0, 0, 0, static_cast<u32>(i), 0, 170 auto thread_res =
171 nullptr, std::move(init_func), init_func_parameter); 171 Thread::Create(system, type, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
172 nullptr, std::move(init_func), init_func_parameter);
173
172 suspend_threads[i] = std::move(thread_res).Unwrap(); 174 suspend_threads[i] = std::move(thread_res).Unwrap();
173 } 175 }
174 } 176 }
@@ -309,7 +311,7 @@ struct KernelCore::Impl {
309 311
310 // This is the kernel's handle table or supervisor handle table which 312 // This is the kernel's handle table or supervisor handle table which
311 // stores all the objects in place. 313 // stores all the objects in place.
312 Kernel::HandleTable global_handle_table; 314 HandleTable global_handle_table;
313 315
314 /// Map of named ports managed by the kernel, which can be retrieved using 316 /// Map of named ports managed by the kernel, which can be retrieved using
315 /// the ConnectToPort SVC. 317 /// the ConnectToPort SVC.
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 49bd47e89..16285c3f0 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -9,6 +9,7 @@
9#include <string> 9#include <string>
10#include <unordered_map> 10#include <unordered_map>
11#include <vector> 11#include <vector>
12#include "core/arm/cpu_interrupt_handler.h"
12#include "core/hardware_properties.h" 13#include "core/hardware_properties.h"
13#include "core/hle/kernel/memory/memory_types.h" 14#include "core/hle/kernel/memory/memory_types.h"
14#include "core/hle/kernel/object.h" 15#include "core/hle/kernel/object.h"
diff --git a/src/core/hle/kernel/memory/address_space_info.cpp b/src/core/hle/kernel/memory/address_space_info.cpp
index a523a2502..e4288cab4 100644
--- a/src/core/hle/kernel/memory/address_space_info.cpp
+++ b/src/core/hle/kernel/memory/address_space_info.cpp
@@ -29,40 +29,39 @@ enum : u64 {
29 29
30// clang-format off 30// clang-format off
31constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{ 31constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{
32 { 32 /*bit_width*/, Size_2_MB /*addr*/, Size_1_GB - Size_2_MB /*size*/, AddressSpaceInfo::Type::Is32Bit, }, 32 { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = AddressSpaceInfo::Type::Is32Bit, },
33 { 32 /*bit_width*/, Size_1_GB /*addr*/, Size_4_GB - Size_1_GB /*size*/, AddressSpaceInfo::Type::Small64Bit, }, 33 { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
34 { 32 /*bit_width*/, Invalid /*addr*/, Size_1_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 34 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Heap, },
35 { 32 /*bit_width*/, Invalid /*addr*/, Size_1_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 35 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Alias, },
36 { 36 /*bit_width*/, Size_128_MB /*addr*/, Size_2_GB - Size_128_MB /*size*/, AddressSpaceInfo::Type::Is32Bit, }, 36 { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Is32Bit, },
37 { 36 /*bit_width*/, Size_2_GB /*addr*/, Size_64_GB - Size_2_GB /*size*/, AddressSpaceInfo::Type::Small64Bit, }, 37 { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
38 { 36 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 38 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
39 { 36 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 39 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Alias, },
40 { 39 /*bit_width*/, Size_128_MB /*addr*/, Size_512_GB - Size_128_MB /*size*/, AddressSpaceInfo::Type::Large64Bit, }, 40 { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Large64Bit, },
41 { 39 /*bit_width*/, Invalid /*addr*/, Size_64_GB /*size*/, AddressSpaceInfo::Type::Is32Bit }, 41 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Is32Bit },
42 { 39 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 42 { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
43 { 39 /*bit_width*/, Invalid /*addr*/, Size_64_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 43 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Alias, },
44 { 39 /*bit_width*/, Invalid /*addr*/, Size_2_GB /*size*/, AddressSpaceInfo::Type::Stack, }, 44 { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = AddressSpaceInfo::Type::Stack, },
45}}; 45}};
46// clang-format on 46// clang-format on
47 47
48constexpr bool IsAllowedIndexForAddress(std::size_t index) { 48constexpr bool IsAllowedIndexForAddress(std::size_t index) {
49 return index < std::size(AddressSpaceInfos) && AddressSpaceInfos[index].GetAddress() != Invalid; 49 return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid;
50} 50}
51 51
52constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 52using IndexArray = std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)>;
53 AddressSpaceIndices32Bit{
54 0, 1, 0, 2, 0, 3,
55 };
56 53
57constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 54constexpr IndexArray AddressSpaceIndices32Bit{
58 AddressSpaceIndices36Bit{ 55 0, 1, 0, 2, 0, 3,
59 4, 5, 4, 6, 4, 7, 56};
60 }; 57
58constexpr IndexArray AddressSpaceIndices36Bit{
59 4, 5, 4, 6, 4, 7,
60};
61 61
62constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 62constexpr IndexArray AddressSpaceIndices39Bit{
63 AddressSpaceIndices39Bit{ 63 9, 8, 8, 10, 12, 11,
64 9, 8, 8, 10, 12, 11, 64};
65 };
66 65
67constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) { 66constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) {
68 return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit && 67 return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
@@ -80,37 +79,37 @@ constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) {
80 79
81} // namespace 80} // namespace
82 81
83u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, AddressSpaceInfo::Type type) { 82u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) {
84 const std::size_t index{static_cast<std::size_t>(type)}; 83 const std::size_t index{static_cast<std::size_t>(type)};
85 switch (width) { 84 switch (width) {
86 case 32: 85 case 32:
87 ASSERT(IsAllowed32BitType(type)); 86 ASSERT(IsAllowed32BitType(type));
88 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index])); 87 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index]));
89 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetAddress(); 88 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].address;
90 case 36: 89 case 36:
91 ASSERT(IsAllowed36BitType(type)); 90 ASSERT(IsAllowed36BitType(type));
92 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index])); 91 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index]));
93 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetAddress(); 92 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].address;
94 case 39: 93 case 39:
95 ASSERT(IsAllowed39BitType(type)); 94 ASSERT(IsAllowed39BitType(type));
96 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index])); 95 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
97 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetAddress(); 96 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address;
98 } 97 }
99 UNREACHABLE(); 98 UNREACHABLE();
100} 99}
101 100
102std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, AddressSpaceInfo::Type type) { 101std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) {
103 const std::size_t index{static_cast<std::size_t>(type)}; 102 const std::size_t index{static_cast<std::size_t>(type)};
104 switch (width) { 103 switch (width) {
105 case 32: 104 case 32:
106 ASSERT(IsAllowed32BitType(type)); 105 ASSERT(IsAllowed32BitType(type));
107 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetSize(); 106 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].size;
108 case 36: 107 case 36:
109 ASSERT(IsAllowed36BitType(type)); 108 ASSERT(IsAllowed36BitType(type));
110 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetSize(); 109 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].size;
111 case 39: 110 case 39:
112 ASSERT(IsAllowed39BitType(type)); 111 ASSERT(IsAllowed39BitType(type));
113 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetSize(); 112 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size;
114 } 113 }
115 UNREACHABLE(); 114 UNREACHABLE();
116} 115}
diff --git a/src/core/hle/kernel/memory/address_space_info.h b/src/core/hle/kernel/memory/address_space_info.h
index c479890be..a4e6e91e5 100644
--- a/src/core/hle/kernel/memory/address_space_info.h
+++ b/src/core/hle/kernel/memory/address_space_info.h
@@ -11,8 +11,7 @@
11 11
12namespace Kernel::Memory { 12namespace Kernel::Memory {
13 13
14class AddressSpaceInfo final : NonCopyable { 14struct AddressSpaceInfo final {
15public:
16 enum class Type : u32 { 15 enum class Type : u32 {
17 Is32Bit = 0, 16 Is32Bit = 0,
18 Small64Bit = 1, 17 Small64Bit = 1,
@@ -23,31 +22,13 @@ public:
23 Count, 22 Count,
24 }; 23 };
25 24
26private:
27 std::size_t bit_width{};
28 std::size_t addr{};
29 std::size_t size{};
30 Type type{};
31
32public:
33 static u64 GetAddressSpaceStart(std::size_t width, Type type); 25 static u64 GetAddressSpaceStart(std::size_t width, Type type);
34 static std::size_t GetAddressSpaceSize(std::size_t width, Type type); 26 static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
35 27
36 constexpr AddressSpaceInfo(std::size_t bit_width, std::size_t addr, std::size_t size, Type type) 28 const std::size_t bit_width{};
37 : bit_width{bit_width}, addr{addr}, size{size}, type{type} {} 29 const std::size_t address{};
38 30 const std::size_t size{};
39 constexpr std::size_t GetWidth() const { 31 const Type type{};
40 return bit_width;
41 }
42 constexpr std::size_t GetAddress() const {
43 return addr;
44 }
45 constexpr std::size_t GetSize() const {
46 return size;
47 }
48 constexpr Type GetType() const {
49 return type;
50 }
51}; 32};
52 33
53} // namespace Kernel::Memory 34} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_layout.h b/src/core/hle/kernel/memory/memory_layout.h
index 830c6f0d7..9b3d6267a 100644
--- a/src/core/hle/kernel/memory/memory_layout.h
+++ b/src/core/hle/kernel/memory/memory_layout.h
@@ -66,8 +66,6 @@ private:
66 const MemoryRegion application; 66 const MemoryRegion application;
67 const MemoryRegion applet; 67 const MemoryRegion applet;
68 const MemoryRegion system; 68 const MemoryRegion system;
69
70 const PAddr start_address{};
71}; 69};
72 70
73} // namespace Kernel::Memory 71} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index c6fcb56ad..ff9d9248b 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -408,7 +408,7 @@ void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
408Process::Process(Core::System& system) 408Process::Process(Core::System& system)
409 : SynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>( 409 : SynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>(
410 system)}, 410 system)},
411 address_arbiter{system}, mutex{system}, system{system} {} 411 handle_table{system.Kernel()}, address_arbiter{system}, mutex{system}, system{system} {}
412 412
413Process::~Process() = default; 413Process::~Process() = default;
414 414
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 9dabe3568..f45cb5674 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -382,12 +382,6 @@ private:
382 /// List of threads waiting for a condition variable 382 /// List of threads waiting for a condition variable
383 std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> cond_var_threads; 383 std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> cond_var_threads;
384 384
385 /// System context
386 Core::System& system;
387
388 /// Name of this process
389 std::string name;
390
391 /// Address of the top of the main thread's stack 385 /// Address of the top of the main thread's stack
392 VAddr main_thread_stack_top{}; 386 VAddr main_thread_stack_top{};
393 387
@@ -399,6 +393,12 @@ private:
399 393
400 /// Process total image size 394 /// Process total image size
401 std::size_t image_size{}; 395 std::size_t image_size{};
396
397 /// Name of this process
398 std::string name;
399
400 /// System context
401 Core::System& system;
402}; 402};
403 403
404} // namespace Kernel 404} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 7b929781c..f93e5e4b0 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -802,7 +802,7 @@ void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
802 802
803void Scheduler::Initialize() { 803void Scheduler::Initialize() {
804 std::string name = "Idle Thread Id:" + std::to_string(core_id); 804 std::string name = "Idle Thread Id:" + std::to_string(core_id);
805 std::function<void(void*)> init_func = system.GetCpuManager().GetIdleThreadStartFunc(); 805 std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc();
806 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 806 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
807 ThreadType type = static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_IDLE); 807 ThreadType type = static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_IDLE);
808 auto thread_res = Thread::Create(system, type, name, 0, 64, 0, static_cast<u32>(core_id), 0, 808 auto thread_res = Thread::Create(system, type, name, 0, 64, 0, static_cast<u32>(core_id), 0,
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 5db19dcf3..01ae57053 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -458,9 +458,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
458 return ERR_OUT_OF_RANGE; 458 return ERR_OUT_OF_RANGE;
459 } 459 }
460 460
461 auto* const thread = system.CurrentScheduler().GetCurrentThread();
462 auto& kernel = system.Kernel(); 461 auto& kernel = system.Kernel();
463 using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type;
464 Thread::ThreadSynchronizationObjects objects(handle_count); 462 Thread::ThreadSynchronizationObjects objects(handle_count);
465 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 463 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
466 464
@@ -1750,9 +1748,9 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1750 // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process 1748 // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process
1751 // them all. 1749 // them all.
1752 std::size_t last = waiting_threads.size(); 1750 std::size_t last = waiting_threads.size();
1753 if (target > 0) 1751 if (target > 0) {
1754 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); 1752 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target));
1755 auto& time_manager = kernel.TimeManager(); 1753 }
1756 for (std::size_t index = 0; index < last; ++index) { 1754 for (std::size_t index = 0; index < last; ++index) {
1757 auto& thread = waiting_threads[index]; 1755 auto& thread = waiting_threads[index];
1758 1756
@@ -1763,7 +1761,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1763 1761
1764 const std::size_t current_core = system.CurrentCoreIndex(); 1762 const std::size_t current_core = system.CurrentCoreIndex();
1765 auto& monitor = system.Monitor(); 1763 auto& monitor = system.Monitor();
1766 auto& memory = system.Memory();
1767 1764
1768 // Atomically read the value of the mutex. 1765 // Atomically read the value of the mutex.
1769 u32 mutex_val = 0; 1766 u32 mutex_val = 0;
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp
index 851b702a5..8b875d853 100644
--- a/src/core/hle/kernel/synchronization.cpp
+++ b/src/core/hle/kernel/synchronization.cpp
@@ -19,7 +19,6 @@ Synchronization::Synchronization(Core::System& system) : system{system} {}
19void Synchronization::SignalObject(SynchronizationObject& obj) const { 19void Synchronization::SignalObject(SynchronizationObject& obj) const {
20 auto& kernel = system.Kernel(); 20 auto& kernel = system.Kernel();
21 SchedulerLock lock(kernel); 21 SchedulerLock lock(kernel);
22 auto& time_manager = kernel.TimeManager();
23 if (obj.IsSignaled()) { 22 if (obj.IsSignaled()) {
24 for (auto thread : obj.GetWaitingThreads()) { 23 for (auto thread : obj.GetWaitingThreads()) {
25 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { 24 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 2b1092697..d132aba34 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -13,16 +13,8 @@
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/thread_queue_list.h" 14#include "common/thread_queue_list.h"
15#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
16#ifdef ARCHITECTURE_x86_64
17#include "core/arm/dynarmic/arm_dynarmic_32.h"
18#include "core/arm/dynarmic/arm_dynarmic_64.h"
19#endif
20#include "core/arm/cpu_interrupt_handler.h"
21#include "core/arm/exclusive_monitor.h"
22#include "core/arm/unicorn/arm_unicorn.h" 16#include "core/arm/unicorn/arm_unicorn.h"
23#include "core/core.h" 17#include "core/core.h"
24#include "core/core_timing.h"
25#include "core/core_timing_util.h"
26#include "core/cpu_manager.h" 18#include "core/cpu_manager.h"
27#include "core/hardware_properties.h" 19#include "core/hardware_properties.h"
28#include "core/hle/kernel/errors.h" 20#include "core/hle/kernel/errors.h"
@@ -36,6 +28,11 @@
36#include "core/hle/result.h" 28#include "core/hle/result.h"
37#include "core/memory.h" 29#include "core/memory.h"
38 30
31#ifdef ARCHITECTURE_x86_64
32#include "core/arm/dynarmic/arm_dynarmic_32.h"
33#include "core/arm/dynarmic/arm_dynarmic_64.h"
34#endif
35
39namespace Kernel { 36namespace Kernel {
40 37
41bool Thread::ShouldWait(const Thread* thread) const { 38bool Thread::ShouldWait(const Thread* thread) const {
@@ -158,7 +155,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
158 std::string name, VAddr entry_point, u32 priority, 155 std::string name, VAddr entry_point, u32 priority,
159 u64 arg, s32 processor_id, VAddr stack_top, 156 u64 arg, s32 processor_id, VAddr stack_top,
160 Process* owner_process) { 157 Process* owner_process) {
161 std::function<void(void*)> init_func = system.GetCpuManager().GetGuestThreadStartFunc(); 158 std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc();
162 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 159 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
163 return Create(system, type_flags, name, entry_point, priority, arg, processor_id, stack_top, 160 return Create(system, type_flags, name, entry_point, priority, arg, processor_id, stack_top,
164 owner_process, std::move(init_func), init_func_parameter); 161 owner_process, std::move(init_func), init_func_parameter);
@@ -540,13 +537,4 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) {
540 return RESULT_SUCCESS; 537 return RESULT_SUCCESS;
541} 538}
542 539
543////////////////////////////////////////////////////////////////////////////////////////////////////
544
545/**
546 * Gets the current thread
547 */
548Thread* GetCurrentThread() {
549 return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
550}
551
552} // namespace Kernel 540} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index c0342c462..8daf79fac 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -583,8 +583,6 @@ private:
583 583
584 void SetCurrentPriority(u32 new_priority); 584 void SetCurrentPriority(u32 new_priority);
585 585
586 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
587
588 Common::SpinLock context_guard{}; 586 Common::SpinLock context_guard{};
589 ThreadContext32 context_32{}; 587 ThreadContext32 context_32{};
590 ThreadContext64 context_64{}; 588 ThreadContext64 context_64{};
@@ -680,9 +678,4 @@ private:
680 std::string name; 678 std::string name;
681}; 679};
682 680
683/**
684 * Gets the current thread
685 */
686Thread* GetCurrentThread();
687
688} // namespace Kernel 681} // namespace Kernel
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index cadc03805..c66124998 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -55,6 +55,10 @@ std::string VfsDirectoryServiceWrapper::GetName() const {
55ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { 55ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const {
56 std::string path(FileUtil::SanitizePath(path_)); 56 std::string path(FileUtil::SanitizePath(path_));
57 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 57 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
58 // dir can be nullptr if path contains subdirectories, create those prior to creating the file.
59 if (dir == nullptr) {
60 dir = backing->CreateSubdirectory(FileUtil::GetParentPath(path));
61 }
58 auto file = dir->CreateFile(FileUtil::GetFilename(path)); 62 auto file = dir->CreateFile(FileUtil::GetFilename(path));
59 if (file == nullptr) { 63 if (file == nullptr) {
60 // TODO(DarkLordZach): Find a better error code for this 64 // TODO(DarkLordZach): Find a better error code for this
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp
new file mode 100644
index 000000000..4730070cb
--- /dev/null
+++ b/src/core/hle/service/mii/manager.cpp
@@ -0,0 +1,484 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <random>
7
8#include "common/assert.h"
9#include "common/file_util.h"
10#include "common/logging/log.h"
11#include "common/string_util.h"
12
13#include "core/hle/service/acc/profile_manager.h"
14#include "core/hle/service/mii/manager.h"
15#include "core/hle/service/mii/raw_data.h"
16#include "core/hle/service/mii/types.h"
17
18namespace Service::Mii {
19
20namespace {
21
22constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
23
24constexpr std::size_t DefaultMiiCount{sizeof(RawData::DefaultMii) / sizeof(DefaultMii)};
25
26constexpr MiiStoreData::Name DefaultMiiName{u'y', u'u', u'z', u'u'};
27constexpr std::array<u8, 8> HairColorLookup{8, 1, 2, 3, 4, 5, 6, 7};
28constexpr std::array<u8, 6> EyeColorLookup{8, 9, 10, 11, 12, 13};
29constexpr std::array<u8, 5> MouthColorLookup{19, 20, 21, 22, 23};
30constexpr std::array<u8, 7> GlassesColorLookup{8, 14, 15, 16, 17, 18, 0};
31constexpr std::array<u8, 62> EyeRotateLookup{
32 {0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
33 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
34 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
35 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04}};
36constexpr std::array<u8, 24> EyebrowRotateLookup{{0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07,
37 0x04, 0x07, 0x06, 0x08, 0x05, 0x05, 0x06, 0x06,
38 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05}};
39
40template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
41std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
42 std::array<T, DestArraySize> out{};
43 std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
44 return out;
45}
46
47MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
48 MiiStoreBitFields bf;
49 std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
50
51 return {
52 .uuid = data.data.uuid,
53 .name = ResizeArray<char16_t, 10, 11>(data.data.name),
54 .font_region = static_cast<u8>(bf.font_region.Value()),
55 .favorite_color = static_cast<u8>(bf.favorite_color.Value()),
56 .gender = static_cast<u8>(bf.gender.Value()),
57 .height = static_cast<u8>(bf.height.Value()),
58 .build = static_cast<u8>(bf.build.Value()),
59 .type = static_cast<u8>(bf.type.Value()),
60 .region_move = static_cast<u8>(bf.region_move.Value()),
61 .faceline_type = static_cast<u8>(bf.faceline_type.Value()),
62 .faceline_color = static_cast<u8>(bf.faceline_color.Value()),
63 .faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()),
64 .faceline_make = static_cast<u8>(bf.faceline_makeup.Value()),
65 .hair_type = static_cast<u8>(bf.hair_type.Value()),
66 .hair_color = static_cast<u8>(bf.hair_color.Value()),
67 .hair_flip = static_cast<u8>(bf.hair_flip.Value()),
68 .eye_type = static_cast<u8>(bf.eye_type.Value()),
69 .eye_color = static_cast<u8>(bf.eye_color.Value()),
70 .eye_scale = static_cast<u8>(bf.eye_scale.Value()),
71 .eye_aspect = static_cast<u8>(bf.eye_aspect.Value()),
72 .eye_rotate = static_cast<u8>(bf.eye_rotate.Value()),
73 .eye_x = static_cast<u8>(bf.eye_x.Value()),
74 .eye_y = static_cast<u8>(bf.eye_y.Value()),
75 .eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()),
76 .eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()),
77 .eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()),
78 .eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()),
79 .eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()),
80 .eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()),
81 .eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3),
82 .nose_type = static_cast<u8>(bf.nose_type.Value()),
83 .nose_scale = static_cast<u8>(bf.nose_scale.Value()),
84 .nose_y = static_cast<u8>(bf.nose_y.Value()),
85 .mouth_type = static_cast<u8>(bf.mouth_type.Value()),
86 .mouth_color = static_cast<u8>(bf.mouth_color.Value()),
87 .mouth_scale = static_cast<u8>(bf.mouth_scale.Value()),
88 .mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()),
89 .mouth_y = static_cast<u8>(bf.mouth_y.Value()),
90 .beard_color = static_cast<u8>(bf.beard_color.Value()),
91 .beard_type = static_cast<u8>(bf.beard_type.Value()),
92 .mustache_type = static_cast<u8>(bf.mustache_type.Value()),
93 .mustache_scale = static_cast<u8>(bf.mustache_scale.Value()),
94 .mustache_y = static_cast<u8>(bf.mustache_y.Value()),
95 .glasses_type = static_cast<u8>(bf.glasses_type.Value()),
96 .glasses_color = static_cast<u8>(bf.glasses_color.Value()),
97 .glasses_scale = static_cast<u8>(bf.glasses_scale.Value()),
98 .glasses_y = static_cast<u8>(bf.glasses_y.Value()),
99 .mole_type = static_cast<u8>(bf.mole_type.Value()),
100 .mole_scale = static_cast<u8>(bf.mole_scale.Value()),
101 .mole_x = static_cast<u8>(bf.mole_x.Value()),
102 .mole_y = static_cast<u8>(bf.mole_y.Value()),
103 };
104}
105
106u16 GenerateCrc16(const void* data, std::size_t size) {
107 s32 crc{};
108 for (std::size_t i = 0; i < size; i++) {
109 crc ^= static_cast<const u8*>(data)[i] << 8;
110 for (std::size_t j = 0; j < 8; j++) {
111 crc <<= 1;
112 if ((crc & 0x10000) != 0) {
113 crc = (crc ^ 0x1021) & 0xFFFF;
114 }
115 }
116 }
117 return Common::swap16(static_cast<u16>(crc));
118}
119
120Common::UUID GenerateValidUUID() {
121 auto uuid{Common::UUID::Generate()};
122
123 // Bit 7 must be set, and bit 6 unset for the UUID to be valid
124 uuid.uuid[1] &= 0xFFFFFFFFFFFFFF3FULL;
125 uuid.uuid[1] |= 0x0000000000000080ULL;
126
127 return uuid;
128}
129
130template <typename T>
131T GetRandomValue(T min, T max) {
132 std::random_device device;
133 std::mt19937 gen(device());
134 std::uniform_int_distribution<u64> distribution(0, static_cast<u64>(max));
135 return static_cast<T>(distribution(gen));
136}
137
138template <typename T>
139T GetRandomValue(T max) {
140 return GetRandomValue<T>({}, max);
141}
142
143template <typename T>
144T GetArrayValue(const u8* data, std::size_t index) {
145 T result{};
146 std::memcpy(&result, &data[index * sizeof(T)], sizeof(T));
147 return result;
148}
149
150MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
151 MiiStoreBitFields bf{};
152
153 if (gender == Gender::All) {
154 gender = GetRandomValue<Gender>(Gender::Maximum);
155 }
156
157 bf.gender.Assign(gender);
158 bf.favorite_color.Assign(GetRandomValue<u8>(11));
159 bf.region_move.Assign(0);
160 bf.font_region.Assign(FontRegion::Standard);
161 bf.type.Assign(0);
162 bf.height.Assign(64);
163 bf.build.Assign(64);
164
165 if (age == Age::All) {
166 const auto temp{GetRandomValue<int>(10)};
167 if (temp >= 8) {
168 age = Age::Old;
169 } else if (temp >= 4) {
170 age = Age::Normal;
171 } else {
172 age = Age::Young;
173 }
174 }
175
176 if (race == Race::All) {
177 const auto temp{GetRandomValue<int>(10)};
178 if (temp >= 8) {
179 race = Race::Black;
180 } else if (temp >= 4) {
181 race = Race::White;
182 } else {
183 race = Race::Asian;
184 }
185 }
186
187 u32 axis_y{};
188 if (gender == Gender::Female && age == Age::Young) {
189 axis_y = GetRandomValue<u32>(3);
190 }
191
192 const std::size_t index{3 * static_cast<std::size_t>(age) +
193 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
194
195 const auto faceline_type_info{
196 GetArrayValue<RandomMiiData4>(&RawData::RandomMiiFaceline[0], index)};
197 const auto faceline_color_info{GetArrayValue<RandomMiiData3>(
198 RawData::RandomMiiFacelineColor.data(),
199 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
200 const auto faceline_wrinkle_info{
201 GetArrayValue<RandomMiiData4>(RawData::RandomMiiFacelineWrinkle.data(), index)};
202 const auto faceline_makeup_info{
203 GetArrayValue<RandomMiiData4>(RawData::RandomMiiFacelineMakeup.data(), index)};
204 const auto hair_type_info{
205 GetArrayValue<RandomMiiData4>(RawData::RandomMiiHairType.data(), index)};
206 const auto hair_color_info{GetArrayValue<RandomMiiData3>(RawData::RandomMiiHairColor.data(),
207 3 * static_cast<std::size_t>(race) +
208 static_cast<std::size_t>(age))};
209 const auto eye_type_info{
210 GetArrayValue<RandomMiiData4>(RawData::RandomMiiEyeType.data(), index)};
211 const auto eye_color_info{GetArrayValue<RandomMiiData2>(RawData::RandomMiiEyeColor.data(),
212 static_cast<std::size_t>(race))};
213 const auto eyebrow_type_info{
214 GetArrayValue<RandomMiiData4>(RawData::RandomMiiEyebrowType.data(), index)};
215 const auto nose_type_info{
216 GetArrayValue<RandomMiiData4>(RawData::RandomMiiNoseType.data(), index)};
217 const auto mouth_type_info{
218 GetArrayValue<RandomMiiData4>(RawData::RandomMiiMouthType.data(), index)};
219 const auto glasses_type_info{GetArrayValue<RandomMiiData2>(RawData::RandomMiiGlassType.data(),
220 static_cast<std::size_t>(age))};
221
222 bf.faceline_type.Assign(
223 faceline_type_info.values[GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
224 bf.faceline_color.Assign(
225 faceline_color_info.values[GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
226 bf.faceline_wrinkle.Assign(
227 faceline_wrinkle_info
228 .values[GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
229 bf.faceline_makeup.Assign(
230 faceline_makeup_info
231 .values[GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
232
233 bf.hair_type.Assign(
234 hair_type_info.values[GetRandomValue<std::size_t>(hair_type_info.values_count)]);
235 bf.hair_color.Assign(
236 HairColorLookup[hair_color_info
237 .values[GetRandomValue<std::size_t>(hair_color_info.values_count)]]);
238 bf.hair_flip.Assign(GetRandomValue<HairFlip>(HairFlip::Maximum));
239
240 bf.eye_type.Assign(
241 eye_type_info.values[GetRandomValue<std::size_t>(eye_type_info.values_count)]);
242
243 const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
244 const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
245 const auto eye_rotate_offset{32 - EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
246 const auto eye_rotate{32 - EyeRotateLookup[bf.eye_type]};
247
248 bf.eye_color.Assign(
249 EyeColorLookup[eye_color_info
250 .values[GetRandomValue<std::size_t>(eye_color_info.values_count)]]);
251 bf.eye_scale.Assign(4);
252 bf.eye_aspect.Assign(3);
253 bf.eye_rotate.Assign(eye_rotate_offset - eye_rotate);
254 bf.eye_x.Assign(2);
255 bf.eye_y.Assign(axis_y + 12);
256
257 bf.eyebrow_type.Assign(
258 eyebrow_type_info.values[GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
259
260 const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
261 const auto eyebrow_y{race == Race::Asian ? 9 : 10};
262 const auto eyebrow_rotate_offset{32 - EyebrowRotateLookup[eyebrow_rotate_1] + 6};
263 const auto eyebrow_rotate{
264 32 - EyebrowRotateLookup[static_cast<std::size_t>(bf.eyebrow_type.Value())]};
265
266 bf.eyebrow_color.Assign(bf.hair_color);
267 bf.eyebrow_scale.Assign(4);
268 bf.eyebrow_aspect.Assign(3);
269 bf.eyebrow_rotate.Assign(eyebrow_rotate_offset - eyebrow_rotate);
270 bf.eyebrow_x.Assign(2);
271 bf.eyebrow_y.Assign(axis_y + eyebrow_y);
272
273 const auto nose_scale{gender == Gender::Female ? 3 : 4};
274
275 bf.nose_type.Assign(
276 nose_type_info.values[GetRandomValue<std::size_t>(nose_type_info.values_count)]);
277 bf.nose_scale.Assign(nose_scale);
278 bf.nose_y.Assign(axis_y + 9);
279
280 const auto mouth_color{gender == Gender::Female ? GetRandomValue<int>(4) : 0};
281
282 bf.mouth_type.Assign(
283 mouth_type_info.values[GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
284 bf.mouth_color.Assign(MouthColorLookup[mouth_color]);
285 bf.mouth_scale.Assign(4);
286 bf.mouth_aspect.Assign(3);
287 bf.mouth_y.Assign(axis_y + 13);
288
289 bf.beard_color.Assign(bf.hair_color);
290 bf.mustache_scale.Assign(4);
291
292 if (gender == Gender::Male && age != Age::Young && GetRandomValue<int>(10) < 2) {
293 const auto mustache_and_beard_flag{
294 GetRandomValue<BeardAndMustacheFlag>(BeardAndMustacheFlag::All)};
295
296 auto beard_type{BeardType::None};
297 auto mustache_type{MustacheType::None};
298
299 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
300 BeardAndMustacheFlag::Beard) {
301 beard_type = GetRandomValue<BeardType>(BeardType::Beard1, BeardType::Beard5);
302 }
303
304 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
305 BeardAndMustacheFlag::Mustache) {
306 mustache_type =
307 GetRandomValue<MustacheType>(MustacheType::Mustache1, MustacheType::Mustache5);
308 }
309
310 bf.mustache_type.Assign(mustache_type);
311 bf.beard_type.Assign(beard_type);
312 bf.mustache_y.Assign(10);
313 } else {
314 bf.mustache_type.Assign(MustacheType::None);
315 bf.beard_type.Assign(BeardType::None);
316 bf.mustache_y.Assign(axis_y + 10);
317 }
318
319 const auto glasses_type_start{GetRandomValue<std::size_t>(100)};
320 u8 glasses_type{};
321 while (glasses_type_start < glasses_type_info.values[glasses_type]) {
322 if (++glasses_type >= glasses_type_info.values_count) {
323 UNREACHABLE();
324 break;
325 }
326 }
327
328 bf.glasses_type.Assign(glasses_type);
329 bf.glasses_color.Assign(GlassesColorLookup[0]);
330 bf.glasses_scale.Assign(4);
331 bf.glasses_y.Assign(axis_y + 10);
332
333 bf.mole_type.Assign(0);
334 bf.mole_scale.Assign(4);
335 bf.mole_x.Assign(2);
336 bf.mole_y.Assign(20);
337
338 return {DefaultMiiName, bf, user_id};
339}
340
341MiiStoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
342 MiiStoreBitFields bf{};
343
344 bf.font_region.Assign(info.font_region);
345 bf.favorite_color.Assign(info.favorite_color);
346 bf.gender.Assign(info.gender);
347 bf.height.Assign(info.height);
348 bf.build.Assign(info.weight);
349 bf.type.Assign(info.type);
350 bf.region_move.Assign(info.region);
351 bf.faceline_type.Assign(info.face_type);
352 bf.faceline_color.Assign(info.face_color);
353 bf.faceline_wrinkle.Assign(info.face_wrinkle);
354 bf.faceline_makeup.Assign(info.face_makeup);
355 bf.hair_type.Assign(info.hair_type);
356 bf.hair_color.Assign(HairColorLookup[info.hair_color]);
357 bf.hair_flip.Assign(static_cast<HairFlip>(info.hair_flip));
358 bf.eye_type.Assign(info.eye_type);
359 bf.eye_color.Assign(EyeColorLookup[info.eye_color]);
360 bf.eye_scale.Assign(info.eye_scale);
361 bf.eye_aspect.Assign(info.eye_aspect);
362 bf.eye_rotate.Assign(info.eye_rotate);
363 bf.eye_x.Assign(info.eye_x);
364 bf.eye_y.Assign(info.eye_y);
365 bf.eyebrow_type.Assign(info.eyebrow_type);
366 bf.eyebrow_color.Assign(HairColorLookup[info.eyebrow_color]);
367 bf.eyebrow_scale.Assign(info.eyebrow_scale);
368 bf.eyebrow_aspect.Assign(info.eyebrow_aspect);
369 bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
370 bf.eyebrow_x.Assign(info.eyebrow_x);
371 bf.eyebrow_y.Assign(info.eyebrow_y - 3);
372 bf.nose_type.Assign(info.nose_type);
373 bf.nose_scale.Assign(info.nose_scale);
374 bf.nose_y.Assign(info.nose_y);
375 bf.mouth_type.Assign(info.mouth_type);
376 bf.mouth_color.Assign(MouthColorLookup[info.mouth_color]);
377 bf.mouth_scale.Assign(info.mouth_scale);
378 bf.mouth_aspect.Assign(info.mouth_aspect);
379 bf.mouth_y.Assign(info.mouth_y);
380 bf.beard_color.Assign(HairColorLookup[info.beard_color]);
381 bf.beard_type.Assign(static_cast<BeardType>(info.beard_type));
382 bf.mustache_type.Assign(static_cast<MustacheType>(info.mustache_type));
383 bf.mustache_scale.Assign(info.mustache_scale);
384 bf.mustache_y.Assign(info.mustache_y);
385 bf.glasses_type.Assign(info.glasses_type);
386 bf.glasses_color.Assign(GlassesColorLookup[info.glasses_color]);
387 bf.glasses_scale.Assign(info.glasses_scale);
388 bf.glasses_y.Assign(info.glasses_y);
389 bf.mole_type.Assign(info.mole_type);
390 bf.mole_scale.Assign(info.mole_scale);
391 bf.mole_x.Assign(info.mole_x);
392 bf.mole_y.Assign(info.mole_y);
393
394 return {DefaultMiiName, bf, user_id};
395}
396
397} // namespace
398
399MiiStoreData::MiiStoreData() = default;
400
401MiiStoreData::MiiStoreData(const MiiStoreData::Name& name, const MiiStoreBitFields& bit_fields,
402 const Common::UUID& user_id) {
403 data.name = name;
404 data.uuid = GenerateValidUUID();
405
406 std::memcpy(data.data.data(), &bit_fields, sizeof(MiiStoreBitFields));
407 data_crc = GenerateCrc16(data.data.data(), sizeof(data));
408 device_crc = GenerateCrc16(&user_id, sizeof(Common::UUID));
409}
410
411MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
412
413bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
414 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
415 return false;
416 }
417
418 const bool result{current_update_counter != update_counter};
419
420 current_update_counter = update_counter;
421
422 return result;
423}
424
425bool MiiManager::IsFullDatabase() const {
426 // TODO(bunnei): We don't implement the Mii database, so it cannot be full
427 return false;
428}
429
430u32 MiiManager::GetCount(SourceFlag source_flag) const {
431 u32 count{};
432 if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
433 // TODO(bunnei): We don't implement the Mii database, but when we do, update this
434 count += 0;
435 }
436 if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
437 count += DefaultMiiCount;
438 }
439 return count;
440}
441
442ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info,
443 SourceFlag source_flag) {
444 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
445 return ERROR_CANNOT_FIND_ENTRY;
446 }
447
448 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
449 return ERROR_CANNOT_FIND_ENTRY;
450}
451
452MiiInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
453 return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
454}
455
456MiiInfo MiiManager::BuildDefault(std::size_t index) {
457 return ConvertStoreDataToInfo(BuildDefaultStoreData(
458 GetArrayValue<DefaultMii>(RawData::DefaultMii.data(), index), user_id));
459}
460
461ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
462 std::vector<MiiInfoElement> result;
463
464 if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
465 return MakeResult(std::move(result));
466 }
467
468 for (std::size_t index = 0; index < DefaultMiiCount; index++) {
469 result.emplace_back(BuildDefault(index), Source::Default);
470 }
471
472 return MakeResult(std::move(result));
473}
474
475ResultCode MiiManager::GetIndex([[maybe_unused]] const MiiInfo& info, u32& index) {
476 constexpr u32 INVALID_INDEX{0xFFFFFFFF};
477
478 index = INVALID_INDEX;
479
480 // TODO(bunnei): We don't implement the Mii database, so we can't have an index
481 return ERROR_CANNOT_FIND_ENTRY;
482}
483
484} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/manager.h b/src/core/hle/service/mii/manager.h
new file mode 100644
index 000000000..927451dea
--- /dev/null
+++ b/src/core/hle/service/mii/manager.h
@@ -0,0 +1,331 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/bit_field.h"
8#include "common/common_funcs.h"
9#include "common/uuid.h"
10#include "core/hle/result.h"
11#include "core/hle/service/mii/types.h"
12
13namespace Service::Mii {
14
15enum class Source : u32 {
16 Database = 0,
17 Default = 1,
18 Account = 2,
19 Friend = 3,
20};
21
22enum class SourceFlag : u32 {
23 None = 0,
24 Database = 1 << 0,
25 Default = 1 << 1,
26};
27DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
28
29struct MiiInfo {
30 Common::UUID uuid{Common::INVALID_UUID};
31 std::array<char16_t, 11> name{};
32 u8 font_region{};
33 u8 favorite_color{};
34 u8 gender{};
35 u8 height{};
36 u8 build{};
37 u8 type{};
38 u8 region_move{};
39 u8 faceline_type{};
40 u8 faceline_color{};
41 u8 faceline_wrinkle{};
42 u8 faceline_make{};
43 u8 hair_type{};
44 u8 hair_color{};
45 u8 hair_flip{};
46 u8 eye_type{};
47 u8 eye_color{};
48 u8 eye_scale{};
49 u8 eye_aspect{};
50 u8 eye_rotate{};
51 u8 eye_x{};
52 u8 eye_y{};
53 u8 eyebrow_type{};
54 u8 eyebrow_color{};
55 u8 eyebrow_scale{};
56 u8 eyebrow_aspect{};
57 u8 eyebrow_rotate{};
58 u8 eyebrow_x{};
59 u8 eyebrow_y{};
60 u8 nose_type{};
61 u8 nose_scale{};
62 u8 nose_y{};
63 u8 mouth_type{};
64 u8 mouth_color{};
65 u8 mouth_scale{};
66 u8 mouth_aspect{};
67 u8 mouth_y{};
68 u8 beard_color{};
69 u8 beard_type{};
70 u8 mustache_type{};
71 u8 mustache_scale{};
72 u8 mustache_y{};
73 u8 glasses_type{};
74 u8 glasses_color{};
75 u8 glasses_scale{};
76 u8 glasses_y{};
77 u8 mole_type{};
78 u8 mole_scale{};
79 u8 mole_x{};
80 u8 mole_y{};
81 INSERT_PADDING_BYTES(1);
82
83 std::u16string Name() const;
84};
85static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
86static_assert(std::has_unique_object_representations_v<MiiInfo>,
87 "All bits of MiiInfo must contribute to its value.");
88
89#pragma pack(push, 4)
90
91struct MiiInfoElement {
92 MiiInfoElement(const MiiInfo& info, Source source) : info{info}, source{source} {}
93
94 MiiInfo info{};
95 Source source{};
96};
97static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
98
99struct MiiStoreBitFields {
100 union {
101 u32 word_0{};
102
103 BitField<0, 8, u32> hair_type;
104 BitField<8, 7, u32> height;
105 BitField<15, 1, u32> mole_type;
106 BitField<16, 7, u32> build;
107 BitField<23, 1, HairFlip> hair_flip;
108 BitField<24, 7, u32> hair_color;
109 BitField<31, 1, u32> type;
110 };
111
112 union {
113 u32 word_1{};
114
115 BitField<0, 7, u32> eye_color;
116 BitField<7, 1, Gender> gender;
117 BitField<8, 7, u32> eyebrow_color;
118 BitField<16, 7, u32> mouth_color;
119 BitField<24, 7, u32> beard_color;
120 };
121
122 union {
123 u32 word_2{};
124
125 BitField<0, 7, u32> glasses_color;
126 BitField<8, 6, u32> eye_type;
127 BitField<14, 2, u32> region_move;
128 BitField<16, 6, u32> mouth_type;
129 BitField<22, 2, FontRegion> font_region;
130 BitField<24, 5, u32> eye_y;
131 BitField<29, 3, u32> glasses_scale;
132 };
133
134 union {
135 u32 word_3{};
136
137 BitField<0, 5, u32> eyebrow_type;
138 BitField<5, 3, MustacheType> mustache_type;
139 BitField<8, 5, u32> nose_type;
140 BitField<13, 3, BeardType> beard_type;
141 BitField<16, 5, u32> nose_y;
142 BitField<21, 3, u32> mouth_aspect;
143 BitField<24, 5, u32> mouth_y;
144 BitField<29, 3, u32> eyebrow_aspect;
145 };
146
147 union {
148 u32 word_4{};
149
150 BitField<0, 5, u32> mustache_y;
151 BitField<5, 3, u32> eye_rotate;
152 BitField<8, 5, u32> glasses_y;
153 BitField<13, 3, u32> eye_aspect;
154 BitField<16, 5, u32> mole_x;
155 BitField<21, 3, u32> eye_scale;
156 BitField<24, 5, u32> mole_y;
157 };
158
159 union {
160 u32 word_5{};
161
162 BitField<0, 5, u32> glasses_type;
163 BitField<8, 4, u32> favorite_color;
164 BitField<12, 4, u32> faceline_type;
165 BitField<16, 4, u32> faceline_color;
166 BitField<20, 4, u32> faceline_wrinkle;
167 BitField<24, 4, u32> faceline_makeup;
168 BitField<28, 4, u32> eye_x;
169 };
170
171 union {
172 u32 word_6{};
173
174 BitField<0, 4, u32> eyebrow_scale;
175 BitField<4, 4, u32> eyebrow_rotate;
176 BitField<8, 4, u32> eyebrow_x;
177 BitField<12, 4, u32> eyebrow_y;
178 BitField<16, 4, u32> nose_scale;
179 BitField<20, 4, u32> mouth_scale;
180 BitField<24, 4, u32> mustache_scale;
181 BitField<28, 4, u32> mole_scale;
182 };
183};
184static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
185static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
186 "MiiStoreBitFields is not trivially copyable.");
187
188struct MiiStoreData {
189 using Name = std::array<char16_t, 10>;
190
191 MiiStoreData();
192 MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
193 const Common::UUID& user_id);
194
195 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
196 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
197 // not suitable for our uses.
198 struct {
199 std::array<u8, 0x1C> data{};
200 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
201
202 Name name{};
203 Common::UUID uuid{Common::INVALID_UUID};
204 } data;
205
206 u16 data_crc{};
207 u16 device_crc{};
208};
209static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
210
211struct MiiStoreDataElement {
212 MiiStoreData data{};
213 Source source{};
214};
215static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
216
217struct MiiDatabase {
218 u32 magic{}; // 'NFDB'
219 std::array<MiiStoreData, 0x64> miis{};
220 INSERT_PADDING_BYTES(1);
221 u8 count{};
222 u16 crc{};
223};
224static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
225
226struct RandomMiiValues {
227 std::array<u8, 0xbc> values{};
228};
229static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
230
231struct RandomMiiData4 {
232 Gender gender{};
233 Age age{};
234 Race race{};
235 u32 values_count{};
236 std::array<u8, 0xbc> values{};
237};
238static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
239
240struct RandomMiiData3 {
241 u32 arg_1;
242 u32 arg_2;
243 u32 values_count;
244 std::array<u8, 0xbc> values{};
245};
246static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
247
248struct RandomMiiData2 {
249 u32 arg_1;
250 u32 values_count;
251 std::array<u8, 0xbc> values{};
252};
253static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
254
255struct DefaultMii {
256 u32 face_type{};
257 u32 face_color{};
258 u32 face_wrinkle{};
259 u32 face_makeup{};
260 u32 hair_type{};
261 u32 hair_color{};
262 u32 hair_flip{};
263 u32 eye_type{};
264 u32 eye_color{};
265 u32 eye_scale{};
266 u32 eye_aspect{};
267 u32 eye_rotate{};
268 u32 eye_x{};
269 u32 eye_y{};
270 u32 eyebrow_type{};
271 u32 eyebrow_color{};
272 u32 eyebrow_scale{};
273 u32 eyebrow_aspect{};
274 u32 eyebrow_rotate{};
275 u32 eyebrow_x{};
276 u32 eyebrow_y{};
277 u32 nose_type{};
278 u32 nose_scale{};
279 u32 nose_y{};
280 u32 mouth_type{};
281 u32 mouth_color{};
282 u32 mouth_scale{};
283 u32 mouth_aspect{};
284 u32 mouth_y{};
285 u32 mustache_type{};
286 u32 beard_type{};
287 u32 beard_color{};
288 u32 mustache_scale{};
289 u32 mustache_y{};
290 u32 glasses_type{};
291 u32 glasses_color{};
292 u32 glasses_scale{};
293 u32 glasses_y{};
294 u32 mole_type{};
295 u32 mole_scale{};
296 u32 mole_x{};
297 u32 mole_y{};
298 u32 height{};
299 u32 weight{};
300 Gender gender{};
301 u32 favorite_color{};
302 u32 region{};
303 FontRegion font_region{};
304 u32 type{};
305 INSERT_PADDING_WORDS(5);
306};
307static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
308
309#pragma pack(pop)
310
311// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
312// with providing an easy interface for HLE emulation of the mii service.
313class MiiManager {
314public:
315 MiiManager();
316
317 bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
318 bool IsFullDatabase() const;
319 u32 GetCount(SourceFlag source_flag) const;
320 ResultVal<MiiInfo> UpdateLatest(const MiiInfo& info, SourceFlag source_flag);
321 MiiInfo BuildRandom(Age age, Gender gender, Race race);
322 MiiInfo BuildDefault(std::size_t index);
323 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
324 ResultCode GetIndex(const MiiInfo& info, u32& index);
325
326private:
327 const Common::UUID user_id;
328 u64 update_counter{};
329};
330
331}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index a128edb43..b81bf6277 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -4,22 +4,17 @@
4 4
5#include <memory> 5#include <memory>
6 6
7#include <fmt/ostream.h>
8
9#include "common/logging/log.h" 7#include "common/logging/log.h"
10#include "common/string_util.h"
11#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
12#include "core/hle/kernel/hle_ipc.h" 9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/mii/manager.h"
13#include "core/hle/service/mii/mii.h" 11#include "core/hle/service/mii/mii.h"
14#include "core/hle/service/mii/mii_manager.h"
15#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
16#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
17 14
18namespace Service::Mii { 15namespace Service::Mii {
19 16
20constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1}; 17constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
21constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
22constexpr ResultCode ERROR_NOT_IN_TEST_MODE{ErrorModule::Mii, 99};
23 18
24class IDatabaseService final : public ServiceFramework<IDatabaseService> { 19class IDatabaseService final : public ServiceFramework<IDatabaseService> {
25public: 20public:
@@ -31,19 +26,19 @@ public:
31 {2, &IDatabaseService::GetCount, "GetCount"}, 26 {2, &IDatabaseService::GetCount, "GetCount"},
32 {3, &IDatabaseService::Get, "Get"}, 27 {3, &IDatabaseService::Get, "Get"},
33 {4, &IDatabaseService::Get1, "Get1"}, 28 {4, &IDatabaseService::Get1, "Get1"},
34 {5, nullptr, "UpdateLatest"}, 29 {5, &IDatabaseService::UpdateLatest, "UpdateLatest"},
35 {6, &IDatabaseService::BuildRandom, "BuildRandom"}, 30 {6, &IDatabaseService::BuildRandom, "BuildRandom"},
36 {7, &IDatabaseService::BuildDefault, "BuildDefault"}, 31 {7, &IDatabaseService::BuildDefault, "BuildDefault"},
37 {8, &IDatabaseService::Get2, "Get2"}, 32 {8, nullptr, "Get2"},
38 {9, &IDatabaseService::Get3, "Get3"}, 33 {9, nullptr, "Get3"},
39 {10, nullptr, "UpdateLatest1"}, 34 {10, nullptr, "UpdateLatest1"},
40 {11, &IDatabaseService::FindIndex, "FindIndex"}, 35 {11, nullptr, "FindIndex"},
41 {12, &IDatabaseService::Move, "Move"}, 36 {12, nullptr, "Move"},
42 {13, &IDatabaseService::AddOrReplace, "AddOrReplace"}, 37 {13, nullptr, "AddOrReplace"},
43 {14, &IDatabaseService::Delete, "Delete"}, 38 {14, nullptr, "Delete"},
44 {15, &IDatabaseService::DestroyFile, "DestroyFile"}, 39 {15, nullptr, "DestroyFile"},
45 {16, &IDatabaseService::DeleteFile, "DeleteFile"}, 40 {16, nullptr, "DeleteFile"},
46 {17, &IDatabaseService::Format, "Format"}, 41 {17, nullptr, "Format"},
47 {18, nullptr, "Import"}, 42 {18, nullptr, "Import"},
48 {19, nullptr, "Export"}, 43 {19, nullptr, "Export"},
49 {20, nullptr, "IsBrokenDatabaseWithClearFlag"}, 44 {20, nullptr, "IsBrokenDatabaseWithClearFlag"},
@@ -59,31 +54,26 @@ public:
59 } 54 }
60 55
61private: 56private:
62 template <typename OutType> 57 template <typename T>
63 std::vector<u8> SerializeArray(OutType (MiiManager::*getter)(u32) const, u32 offset, 58 std::vector<u8> SerializeArray(const std::vector<T>& values) {
64 u32 requested_size, u32& read_size) { 59 std::vector<u8> out(values.size() * sizeof(T));
65 read_size = std::min(requested_size, db.Size() - offset); 60 std::size_t offset{};
66 61 for (const auto& value : values) {
67 std::vector<u8> out(read_size * sizeof(OutType)); 62 std::memcpy(out.data() + offset, &value, sizeof(T));
68 63 offset += sizeof(T);
69 for (u32 i = 0; i < read_size; ++i) {
70 const auto obj = (db.*getter)(offset + i);
71 std::memcpy(out.data() + i * sizeof(OutType), &obj, sizeof(OutType));
72 } 64 }
73
74 return out; 65 return out;
75 } 66 }
76 67
77 void IsUpdated(Kernel::HLERequestContext& ctx) { 68 void IsUpdated(Kernel::HLERequestContext& ctx) {
78 IPC::RequestParser rp{ctx}; 69 IPC::RequestParser rp{ctx};
79 const auto source{rp.PopRaw<Source>()}; 70 const auto source_flag{rp.PopRaw<SourceFlag>()};
80 71
81 LOG_DEBUG(Service_Mii, "called with source={}", source); 72 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
82 73
83 IPC::ResponseBuilder rb{ctx, 3}; 74 IPC::ResponseBuilder rb{ctx, 3};
84 rb.Push(RESULT_SUCCESS); 75 rb.Push(RESULT_SUCCESS);
85 rb.Push(db.CheckUpdatedFlag()); 76 rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter));
86 db.ResetUpdatedFlag();
87 } 77 }
88 78
89 void IsFullDatabase(Kernel::HLERequestContext& ctx) { 79 void IsFullDatabase(Kernel::HLERequestContext& ctx) {
@@ -91,264 +81,149 @@ private:
91 81
92 IPC::ResponseBuilder rb{ctx, 3}; 82 IPC::ResponseBuilder rb{ctx, 3};
93 rb.Push(RESULT_SUCCESS); 83 rb.Push(RESULT_SUCCESS);
94 rb.Push(db.Full()); 84 rb.Push(manager.IsFullDatabase());
95 } 85 }
96 86
97 void GetCount(Kernel::HLERequestContext& ctx) { 87 void GetCount(Kernel::HLERequestContext& ctx) {
98 IPC::RequestParser rp{ctx}; 88 IPC::RequestParser rp{ctx};
99 const auto source{rp.PopRaw<Source>()}; 89 const auto source_flag{rp.PopRaw<SourceFlag>()};
100 90
101 LOG_DEBUG(Service_Mii, "called with source={}", source); 91 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
102 92
103 IPC::ResponseBuilder rb{ctx, 3}; 93 IPC::ResponseBuilder rb{ctx, 3};
104 rb.Push(RESULT_SUCCESS); 94 rb.Push(RESULT_SUCCESS);
105 rb.Push<u32>(db.Size()); 95 rb.Push<u32>(manager.GetCount(source_flag));
106 } 96 }
107 97
108 // Gets Miis from database at offset and index in format MiiInfoElement
109 void Get(Kernel::HLERequestContext& ctx) { 98 void Get(Kernel::HLERequestContext& ctx) {
110 IPC::RequestParser rp{ctx}; 99 IPC::RequestParser rp{ctx};
111 const auto size{rp.PopRaw<u32>()}; 100 const auto source_flag{rp.PopRaw<SourceFlag>()};
112 const auto source{rp.PopRaw<Source>()};
113
114 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
115 offsets[0], source);
116
117 u32 read_size{};
118 ctx.WriteBuffer(SerializeArray(&MiiManager::GetInfoElement, offsets[0], size, read_size));
119 offsets[0] += read_size;
120
121 IPC::ResponseBuilder rb{ctx, 3};
122 rb.Push(RESULT_SUCCESS);
123 rb.Push<u32>(read_size);
124 }
125 101
126 // Gets Miis from database at offset and index in format MiiInfo 102 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
127 void Get1(Kernel::HLERequestContext& ctx) {
128 IPC::RequestParser rp{ctx};
129 const auto size{rp.PopRaw<u32>()};
130 const auto source{rp.PopRaw<Source>()};
131 103
132 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size, 104 const auto result{manager.GetDefault(source_flag)};
133 offsets[1], source); 105 if (result.Failed()) {
106 IPC::ResponseBuilder rb{ctx, 2};
107 rb.Push(result.Code());
108 return;
109 }
134 110
135 u32 read_size{}; 111 if (result->size() > 0) {
136 ctx.WriteBuffer(SerializeArray(&MiiManager::GetInfo, offsets[1], size, read_size)); 112 ctx.WriteBuffer(SerializeArray(*result));
137 offsets[1] += read_size; 113 }
138 114
139 IPC::ResponseBuilder rb{ctx, 3}; 115 IPC::ResponseBuilder rb{ctx, 3};
140 rb.Push(RESULT_SUCCESS); 116 rb.Push(RESULT_SUCCESS);
141 rb.Push<u32>(read_size); 117 rb.Push<u32>(static_cast<u32>(result->size()));
142 } 118 }
143 119
144 void BuildRandom(Kernel::HLERequestContext& ctx) { 120 void Get1(Kernel::HLERequestContext& ctx) {
145 IPC::RequestParser rp{ctx}; 121 IPC::RequestParser rp{ctx};
146 const auto [unknown1, unknown2, unknown3] = rp.PopRaw<RandomParameters>(); 122 const auto source_flag{rp.PopRaw<SourceFlag>()};
147 123
148 if (unknown1 > 3) { 124 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
149 IPC::ResponseBuilder rb{ctx, 2};
150 rb.Push(ERROR_INVALID_ARGUMENT);
151 LOG_ERROR(Service_Mii, "Invalid unknown1 value: {}", unknown1);
152 return;
153 }
154 125
155 if (unknown2 > 2) { 126 const auto result{manager.GetDefault(source_flag)};
127 if (result.Failed()) {
156 IPC::ResponseBuilder rb{ctx, 2}; 128 IPC::ResponseBuilder rb{ctx, 2};
157 rb.Push(ERROR_INVALID_ARGUMENT); 129 rb.Push(result.Code());
158 LOG_ERROR(Service_Mii, "Invalid unknown2 value: {}", unknown2);
159 return; 130 return;
160 } 131 }
161 132
162 if (unknown3 > 3) { 133 std::vector<MiiInfo> values;
163 IPC::ResponseBuilder rb{ctx, 2}; 134 for (const auto& element : *result) {
164 rb.Push(ERROR_INVALID_ARGUMENT); 135 values.emplace_back(element.info);
165 LOG_ERROR(Service_Mii, "Invalid unknown3 value: {}", unknown3);
166 return;
167 } 136 }
168 137
169 LOG_DEBUG(Service_Mii, "called with param_1={:08X}, param_2={:08X}, param_3={:08X}", 138 ctx.WriteBuffer(SerializeArray(values));
170 unknown1, unknown2, unknown3);
171 139
172 const auto info = db.CreateRandom({unknown1, unknown2, unknown3}); 140 IPC::ResponseBuilder rb{ctx, 3};
173 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
174 rb.Push(RESULT_SUCCESS); 141 rb.Push(RESULT_SUCCESS);
175 rb.PushRaw<MiiInfo>(info); 142 rb.Push<u32>(static_cast<u32>(result->size()));
176 } 143 }
177 144
178 void BuildDefault(Kernel::HLERequestContext& ctx) { 145 void UpdateLatest(Kernel::HLERequestContext& ctx) {
179 IPC::RequestParser rp{ctx}; 146 IPC::RequestParser rp{ctx};
180 const auto index{rp.PopRaw<u32>()}; 147 const auto info{rp.PopRaw<MiiInfo>()};
148 const auto source_flag{rp.PopRaw<SourceFlag>()};
181 149
182 if (index > 5) { 150 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
183 LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}", 151
184 index); 152 const auto result{manager.UpdateLatest(info, source_flag)};
153 if (result.Failed()) {
185 IPC::ResponseBuilder rb{ctx, 2}; 154 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(ERROR_INVALID_ARGUMENT); 155 rb.Push(result.Code());
187 return; 156 return;
188 } 157 }
189 158
190 LOG_DEBUG(Service_Mii, "called with index={:08X}", index);
191
192 const auto info = db.CreateDefault(index);
193 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)}; 159 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
194 rb.Push(RESULT_SUCCESS); 160 rb.Push(RESULT_SUCCESS);
195 rb.PushRaw<MiiInfo>(info); 161 rb.PushRaw<MiiInfo>(*result);
196 } 162 }
197 163
198 // Gets Miis from database at offset and index in format MiiStoreDataElement 164 void BuildRandom(Kernel::HLERequestContext& ctx) {
199 void Get2(Kernel::HLERequestContext& ctx) {
200 IPC::RequestParser rp{ctx};
201 const auto size{rp.PopRaw<u32>()};
202 const auto source{rp.PopRaw<Source>()};
203
204 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
205 offsets[2], source);
206
207 u32 read_size{};
208 ctx.WriteBuffer(
209 SerializeArray(&MiiManager::GetStoreDataElement, offsets[2], size, read_size));
210 offsets[2] += read_size;
211
212 IPC::ResponseBuilder rb{ctx, 3};
213 rb.Push(RESULT_SUCCESS);
214 rb.Push<u32>(read_size);
215 }
216
217 // Gets Miis from database at offset and index in format MiiStoreData
218 void Get3(Kernel::HLERequestContext& ctx) {
219 IPC::RequestParser rp{ctx};
220 const auto size{rp.PopRaw<u32>()};
221 const auto source{rp.PopRaw<Source>()};
222
223 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
224 offsets[3], source);
225
226 u32 read_size{};
227 ctx.WriteBuffer(SerializeArray(&MiiManager::GetStoreData, offsets[3], size, read_size));
228 offsets[3] += read_size;
229
230 IPC::ResponseBuilder rb{ctx, 3};
231 rb.Push(RESULT_SUCCESS);
232 rb.Push<u32>(read_size);
233 }
234
235 void FindIndex(Kernel::HLERequestContext& ctx) {
236 IPC::RequestParser rp{ctx}; 165 IPC::RequestParser rp{ctx};
237 const auto uuid{rp.PopRaw<Common::UUID>()};
238 const auto unknown{rp.PopRaw<bool>()};
239 166
240 LOG_DEBUG(Service_Mii, "called with uuid={}, unknown={}", uuid.FormatSwitch(), unknown); 167 const auto age{rp.PopRaw<Age>()};
168 const auto gender{rp.PopRaw<Gender>()};
169 const auto race{rp.PopRaw<Race>()};
241 170
242 IPC::ResponseBuilder rb{ctx, 3}; 171 LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race);
243 172
244 const auto index = db.IndexOf(uuid); 173 if (age > Age::All) {
245 if (index > MAX_MIIS) { 174 IPC::ResponseBuilder rb{ctx, 2};
246 // TODO(DarkLordZach): Find a better error code 175 rb.Push(ERROR_INVALID_ARGUMENT);
247 rb.Push(RESULT_UNKNOWN); 176 LOG_ERROR(Service_Mii, "invalid age={}", age);
248 rb.Push(index); 177 return;
249 } else {
250 rb.Push(RESULT_SUCCESS);
251 rb.Push(index);
252 } 178 }
253 }
254 179
255 void Move(Kernel::HLERequestContext& ctx) { 180 if (gender > Gender::All) {
256 IPC::RequestParser rp{ctx};
257 const auto uuid{rp.PopRaw<Common::UUID>()};
258 const auto index{rp.PopRaw<s32>()};
259
260 if (index < 0) {
261 LOG_ERROR(Service_Mii, "Index cannot be negative but is {:08X}!", index);
262 IPC::ResponseBuilder rb{ctx, 2}; 181 IPC::ResponseBuilder rb{ctx, 2};
263 rb.Push(ERROR_INVALID_ARGUMENT); 182 rb.Push(ERROR_INVALID_ARGUMENT);
183 LOG_ERROR(Service_Mii, "invalid gender={}", gender);
264 return; 184 return;
265 } 185 }
266 186
267 LOG_DEBUG(Service_Mii, "called with uuid={}, index={:08X}", uuid.FormatSwitch(), index); 187 if (race > Race::All) {
268
269 const auto success = db.Move(uuid, index);
270
271 IPC::ResponseBuilder rb{ctx, 2};
272 // TODO(DarkLordZach): Find a better error code
273 rb.Push(success ? RESULT_SUCCESS : RESULT_UNKNOWN);
274 }
275
276 void AddOrReplace(Kernel::HLERequestContext& ctx) {
277 IPC::RequestParser rp{ctx};
278 const auto data{rp.PopRaw<MiiStoreData>()};
279
280 LOG_DEBUG(Service_Mii, "called with Mii data uuid={}, name={}", data.uuid.FormatSwitch(),
281 Common::UTF16ToUTF8(data.Name()));
282
283 const auto success = db.AddOrReplace(data);
284
285 IPC::ResponseBuilder rb{ctx, 2};
286 // TODO(DarkLordZach): Find a better error code
287 rb.Push(success ? RESULT_SUCCESS : RESULT_UNKNOWN);
288 }
289
290 void Delete(Kernel::HLERequestContext& ctx) {
291 IPC::RequestParser rp{ctx};
292 const auto uuid{rp.PopRaw<Common::UUID>()};
293
294 LOG_DEBUG(Service_Mii, "called with uuid={}", uuid.FormatSwitch());
295
296 const auto success = db.Remove(uuid);
297
298 IPC::ResponseBuilder rb{ctx, 2};
299 rb.Push(success ? RESULT_SUCCESS : ERROR_CANNOT_FIND_ENTRY);
300 }
301
302 void DestroyFile(Kernel::HLERequestContext& ctx) {
303 LOG_DEBUG(Service_Mii, "called");
304
305 if (!db.IsTestModeEnabled()) {
306 LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot destory database file.");
307 IPC::ResponseBuilder rb{ctx, 2}; 188 IPC::ResponseBuilder rb{ctx, 2};
308 rb.Push(ERROR_NOT_IN_TEST_MODE); 189 rb.Push(ERROR_INVALID_ARGUMENT);
190 LOG_ERROR(Service_Mii, "invalid race={}", race);
309 return; 191 return;
310 } 192 }
311 193
312 IPC::ResponseBuilder rb{ctx, 3}; 194 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
313 rb.Push(RESULT_SUCCESS); 195 rb.Push(RESULT_SUCCESS);
314 rb.Push(db.DestroyFile()); 196 rb.PushRaw<MiiInfo>(manager.BuildRandom(age, gender, race));
315 } 197 }
316 198
317 void DeleteFile(Kernel::HLERequestContext& ctx) { 199 void BuildDefault(Kernel::HLERequestContext& ctx) {
318 LOG_DEBUG(Service_Mii, "called"); 200 IPC::RequestParser rp{ctx};
201 const auto index{rp.Pop<u32>()};
202
203 LOG_DEBUG(Service_Mii, "called with index={}", index);
319 204
320 if (!db.IsTestModeEnabled()) { 205 if (index > 5) {
321 LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot delete database file."); 206 LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
207 index);
322 IPC::ResponseBuilder rb{ctx, 2}; 208 IPC::ResponseBuilder rb{ctx, 2};
323 rb.Push(ERROR_NOT_IN_TEST_MODE); 209 rb.Push(ERROR_INVALID_ARGUMENT);
324 return; 210 return;
325 } 211 }
326 212
327 IPC::ResponseBuilder rb{ctx, 3}; 213 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
328 rb.Push(RESULT_SUCCESS);
329 rb.Push(db.DeleteFile());
330 }
331
332 void Format(Kernel::HLERequestContext& ctx) {
333 LOG_DEBUG(Service_Mii, "called");
334
335 db.Clear();
336
337 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(RESULT_SUCCESS); 214 rb.Push(RESULT_SUCCESS);
215 rb.PushRaw<MiiInfo>(manager.BuildDefault(index));
339 } 216 }
340 217
341 void GetIndex(Kernel::HLERequestContext& ctx) { 218 void GetIndex(Kernel::HLERequestContext& ctx) {
342 IPC::RequestParser rp{ctx}; 219 IPC::RequestParser rp{ctx};
343 const auto info{rp.PopRaw<MiiInfo>()}; 220 const auto info{rp.PopRaw<MiiInfo>()};
344 221
345 LOG_DEBUG(Service_Mii, "called with Mii info uuid={}, name={}", info.uuid.FormatSwitch(), 222 LOG_DEBUG(Service_Mii, "called");
346 Common::UTF16ToUTF8(info.Name()));
347
348 const auto index = db.IndexOf(info);
349 223
350 IPC::ResponseBuilder rb{ctx, 2}; 224 u32 index{};
351 rb.Push(RESULT_SUCCESS); 225 IPC::ResponseBuilder rb{ctx, 3};
226 rb.Push(manager.GetIndex(info, index));
352 rb.Push(index); 227 rb.Push(index);
353 } 228 }
354 229
@@ -364,12 +239,14 @@ private:
364 rb.Push(RESULT_SUCCESS); 239 rb.Push(RESULT_SUCCESS);
365 } 240 }
366 241
367 MiiManager db; 242 constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
243 return current_interface_version >= interface_version;
244 }
368 245
369 u32 current_interface_version = 0; 246 MiiManager manager;
370 247
371 // Last read offsets of Get functions 248 u32 current_interface_version{};
372 std::array<u32, 4> offsets{}; 249 u64 current_update_counter{};
373}; 250};
374 251
375class MiiDBModule final : public ServiceFramework<MiiDBModule> { 252class MiiDBModule final : public ServiceFramework<MiiDBModule> {
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
deleted file mode 100644
index 8d0353075..000000000
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstring>
7#include "common/assert.h"
8#include "common/file_util.h"
9#include "common/logging/log.h"
10#include "common/string_util.h"
11#include "core/hle/service/mii/mii_manager.h"
12
13namespace Service::Mii {
14
15namespace {
16
17constexpr char MII_SAVE_DATABASE_PATH[] = "/system/save/8000000000000030/MiiDatabase.dat";
18constexpr std::array<char16_t, 11> DEFAULT_MII_NAME = {u'y', u'u', u'z', u'u', u'\0'};
19
20// This value was retrieved from HW test
21constexpr MiiStoreData DEFAULT_MII = {
22 {
23 0x21, 0x40, 0x40, 0x01, 0x08, 0x01, 0x13, 0x08, 0x08, 0x02, 0x17, 0x8C, 0x06, 0x01,
24 0x69, 0x6D, 0x8A, 0x6A, 0x82, 0x14, 0x00, 0x00, 0x00, 0x20, 0x64, 0x72, 0x44, 0x44,
25 },
26 {'y', 'u', 'z', 'u', '\0'},
27 Common::UUID{1, 0},
28 0,
29 0,
30};
31
32// Default values taken from multiple real databases
33const MiiDatabase DEFAULT_MII_DATABASE{Common::MakeMagic('N', 'F', 'D', 'B'), {}, {1}, 0, 0};
34
35constexpr std::array<const char*, 4> SOURCE_NAMES{
36 "Database",
37 "Default",
38 "Account",
39 "Friend",
40};
41
42template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
43std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
44 std::array<T, DestArraySize> out{};
45 std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
46 return out;
47}
48
49MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
50 MiiStoreBitFields bf{};
51 std::memcpy(&bf, data.data.data(), sizeof(MiiStoreBitFields));
52 return {
53 data.uuid,
54 ResizeArray<char16_t, 10, 11>(data.name),
55 static_cast<u8>(bf.font_region.Value()),
56 static_cast<u8>(bf.favorite_color.Value()),
57 static_cast<u8>(bf.gender.Value()),
58 static_cast<u8>(bf.height.Value()),
59 static_cast<u8>(bf.weight.Value()),
60 static_cast<u8>(bf.mii_type.Value()),
61 static_cast<u8>(bf.mii_region.Value()),
62 static_cast<u8>(bf.face_type.Value()),
63 static_cast<u8>(bf.face_color.Value()),
64 static_cast<u8>(bf.face_wrinkle.Value()),
65 static_cast<u8>(bf.face_makeup.Value()),
66 static_cast<u8>(bf.hair_type.Value()),
67 static_cast<u8>(bf.hair_color.Value()),
68 static_cast<bool>(bf.hair_flip.Value()),
69 static_cast<u8>(bf.eye_type.Value()),
70 static_cast<u8>(bf.eye_color.Value()),
71 static_cast<u8>(bf.eye_scale.Value()),
72 static_cast<u8>(bf.eye_aspect.Value()),
73 static_cast<u8>(bf.eye_rotate.Value()),
74 static_cast<u8>(bf.eye_x.Value()),
75 static_cast<u8>(bf.eye_y.Value()),
76 static_cast<u8>(bf.eyebrow_type.Value()),
77 static_cast<u8>(bf.eyebrow_color.Value()),
78 static_cast<u8>(bf.eyebrow_scale.Value()),
79 static_cast<u8>(bf.eyebrow_aspect.Value()),
80 static_cast<u8>(bf.eyebrow_rotate.Value()),
81 static_cast<u8>(bf.eyebrow_x.Value()),
82 static_cast<u8>(bf.eyebrow_y.Value()),
83 static_cast<u8>(bf.nose_type.Value()),
84 static_cast<u8>(bf.nose_scale.Value()),
85 static_cast<u8>(bf.nose_y.Value()),
86 static_cast<u8>(bf.mouth_type.Value()),
87 static_cast<u8>(bf.mouth_color.Value()),
88 static_cast<u8>(bf.mouth_scale.Value()),
89 static_cast<u8>(bf.mouth_aspect.Value()),
90 static_cast<u8>(bf.mouth_y.Value()),
91 static_cast<u8>(bf.facial_hair_color.Value()),
92 static_cast<u8>(bf.beard_type.Value()),
93 static_cast<u8>(bf.mustache_type.Value()),
94 static_cast<u8>(bf.mustache_scale.Value()),
95 static_cast<u8>(bf.mustache_y.Value()),
96 static_cast<u8>(bf.glasses_type.Value()),
97 static_cast<u8>(bf.glasses_color.Value()),
98 static_cast<u8>(bf.glasses_scale.Value()),
99 static_cast<u8>(bf.glasses_y.Value()),
100 static_cast<u8>(bf.mole_type.Value()),
101 static_cast<u8>(bf.mole_scale.Value()),
102 static_cast<u8>(bf.mole_x.Value()),
103 static_cast<u8>(bf.mole_y.Value()),
104 0x00,
105 };
106}
107MiiStoreData ConvertInfoToStoreData(const MiiInfo& info) {
108 MiiStoreData out{};
109 out.name = ResizeArray<char16_t, 11, 10>(info.name);
110 out.uuid = info.uuid;
111
112 MiiStoreBitFields bf{};
113
114 bf.hair_type.Assign(info.hair_type);
115 bf.mole_type.Assign(info.mole_type);
116 bf.height.Assign(info.height);
117 bf.hair_flip.Assign(info.hair_flip);
118 bf.weight.Assign(info.weight);
119 bf.hair_color.Assign(info.hair_color);
120
121 bf.gender.Assign(info.gender);
122 bf.eye_color.Assign(info.eye_color);
123 bf.eyebrow_color.Assign(info.eyebrow_color);
124 bf.mouth_color.Assign(info.mouth_color);
125 bf.facial_hair_color.Assign(info.facial_hair_color);
126
127 bf.mii_type.Assign(info.mii_type);
128 bf.glasses_color.Assign(info.glasses_color);
129 bf.font_region.Assign(info.font_region);
130 bf.eye_type.Assign(info.eye_type);
131 bf.mii_region.Assign(info.mii_region);
132 bf.mouth_type.Assign(info.mouth_type);
133 bf.glasses_scale.Assign(info.glasses_scale);
134 bf.eye_y.Assign(info.eye_y);
135
136 bf.mustache_type.Assign(info.mustache_type);
137 bf.eyebrow_type.Assign(info.eyebrow_type);
138 bf.beard_type.Assign(info.beard_type);
139 bf.nose_type.Assign(info.nose_type);
140 bf.mouth_aspect.Assign(info.mouth_aspect_ratio);
141 bf.nose_y.Assign(info.nose_y);
142 bf.eyebrow_aspect.Assign(info.eyebrow_aspect_ratio);
143 bf.mouth_y.Assign(info.mouth_y);
144
145 bf.eye_rotate.Assign(info.eye_rotate);
146 bf.mustache_y.Assign(info.mustache_y);
147 bf.eye_aspect.Assign(info.eye_aspect_ratio);
148 bf.glasses_y.Assign(info.glasses_y);
149 bf.eye_scale.Assign(info.eye_scale);
150 bf.mole_x.Assign(info.mole_x);
151 bf.mole_y.Assign(info.mole_y);
152
153 bf.glasses_type.Assign(info.glasses_type);
154 bf.face_type.Assign(info.face_type);
155 bf.favorite_color.Assign(info.favorite_color);
156 bf.face_wrinkle.Assign(info.face_wrinkle);
157 bf.face_color.Assign(info.face_color);
158 bf.eye_x.Assign(info.eye_x);
159 bf.face_makeup.Assign(info.face_makeup);
160
161 bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
162 bf.eyebrow_scale.Assign(info.eyebrow_scale);
163 bf.eyebrow_y.Assign(info.eyebrow_y);
164 bf.eyebrow_x.Assign(info.eyebrow_x);
165 bf.mouth_scale.Assign(info.mouth_scale);
166 bf.nose_scale.Assign(info.nose_scale);
167 bf.mole_scale.Assign(info.mole_scale);
168 bf.mustache_scale.Assign(info.mustache_scale);
169
170 std::memcpy(out.data.data(), &bf, sizeof(MiiStoreBitFields));
171
172 return out;
173}
174
175} // namespace
176
177std::ostream& operator<<(std::ostream& os, Source source) {
178 if (static_cast<std::size_t>(source) >= SOURCE_NAMES.size()) {
179 return os << "[UNKNOWN SOURCE]";
180 }
181
182 os << SOURCE_NAMES.at(static_cast<std::size_t>(source));
183 return os;
184}
185
186std::u16string MiiInfo::Name() const {
187 return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size());
188}
189
190bool operator==(const MiiInfo& lhs, const MiiInfo& rhs) {
191 return std::memcmp(&lhs, &rhs, sizeof(MiiInfo)) == 0;
192}
193
194bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs) {
195 return !operator==(lhs, rhs);
196}
197
198std::u16string MiiStoreData::Name() const {
199 return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size());
200}
201
202MiiManager::MiiManager() = default;
203
204MiiManager::~MiiManager() = default;
205
206MiiInfo MiiManager::CreateRandom(RandomParameters params) {
207 LOG_WARNING(Service_Mii,
208 "(STUBBED) called with params={:08X}{:08X}{:08X}, returning default Mii",
209 params.unknown_1, params.unknown_2, params.unknown_3);
210
211 return ConvertStoreDataToInfo(CreateMiiWithUniqueUUID());
212}
213
214MiiInfo MiiManager::CreateDefault(u32 index) {
215 const auto new_mii = CreateMiiWithUniqueUUID();
216
217 database.miis.at(index) = new_mii;
218
219 EnsureDatabasePartition();
220 return ConvertStoreDataToInfo(new_mii);
221}
222
223bool MiiManager::CheckUpdatedFlag() const {
224 return updated_flag;
225}
226
227void MiiManager::ResetUpdatedFlag() {
228 updated_flag = false;
229}
230
231bool MiiManager::IsTestModeEnabled() const {
232 return is_test_mode_enabled;
233}
234
235bool MiiManager::Empty() const {
236 return Size() == 0;
237}
238
239bool MiiManager::Full() const {
240 return Size() == MAX_MIIS;
241}
242
243void MiiManager::Clear() {
244 updated_flag = true;
245 std::fill(database.miis.begin(), database.miis.end(), MiiStoreData{});
246}
247
248u32 MiiManager::Size() const {
249 return static_cast<u32>(std::count_if(database.miis.begin(), database.miis.end(),
250 [](const MiiStoreData& elem) { return elem.uuid; }));
251}
252
253MiiInfo MiiManager::GetInfo(u32 index) const {
254 return ConvertStoreDataToInfo(GetStoreData(index));
255}
256
257MiiInfoElement MiiManager::GetInfoElement(u32 index) const {
258 return {GetInfo(index), Source::Database};
259}
260
261MiiStoreData MiiManager::GetStoreData(u32 index) const {
262 return database.miis.at(index);
263}
264
265MiiStoreDataElement MiiManager::GetStoreDataElement(u32 index) const {
266 return {GetStoreData(index), Source::Database};
267}
268
269bool MiiManager::Remove(Common::UUID uuid) {
270 const auto iter = std::find_if(database.miis.begin(), database.miis.end(),
271 [uuid](const MiiStoreData& elem) { return elem.uuid == uuid; });
272
273 if (iter == database.miis.end())
274 return false;
275
276 updated_flag = true;
277 *iter = MiiStoreData{};
278 EnsureDatabasePartition();
279 return true;
280}
281
282u32 MiiManager::IndexOf(Common::UUID uuid) const {
283 const auto iter = std::find_if(database.miis.begin(), database.miis.end(),
284 [uuid](const MiiStoreData& elem) { return elem.uuid == uuid; });
285
286 if (iter == database.miis.end())
287 return INVALID_INDEX;
288
289 return static_cast<u32>(std::distance(database.miis.begin(), iter));
290}
291
292u32 MiiManager::IndexOf(const MiiInfo& info) const {
293 const auto iter =
294 std::find_if(database.miis.begin(), database.miis.end(), [&info](const MiiStoreData& elem) {
295 return ConvertStoreDataToInfo(elem) == info;
296 });
297
298 if (iter == database.miis.end())
299 return INVALID_INDEX;
300
301 return static_cast<u32>(std::distance(database.miis.begin(), iter));
302}
303
304bool MiiManager::Move(Common::UUID uuid, u32 new_index) {
305 const auto index = IndexOf(uuid);
306
307 if (index == INVALID_INDEX || new_index >= MAX_MIIS)
308 return false;
309
310 updated_flag = true;
311 const auto moving = database.miis[index];
312 const auto replacing = database.miis[new_index];
313 if (replacing.uuid) {
314 database.miis[index] = replacing;
315 database.miis[new_index] = moving;
316 } else {
317 database.miis[index] = MiiStoreData{};
318 database.miis[new_index] = moving;
319 }
320
321 EnsureDatabasePartition();
322 return true;
323}
324
325bool MiiManager::AddOrReplace(const MiiStoreData& data) {
326 const auto index = IndexOf(data.uuid);
327
328 updated_flag = true;
329 if (index == INVALID_INDEX) {
330 const auto size = Size();
331 if (size == MAX_MIIS)
332 return false;
333 database.miis[size] = data;
334 } else {
335 database.miis[index] = data;
336 }
337
338 return true;
339}
340
341bool MiiManager::DestroyFile() {
342 database = DEFAULT_MII_DATABASE;
343 updated_flag = false;
344 return DeleteFile();
345}
346
347bool MiiManager::DeleteFile() {
348 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH;
349 return FileUtil::Exists(path) && FileUtil::Delete(path);
350}
351
352void MiiManager::WriteToFile() {
353 const auto raw_path =
354 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000030";
355 if (FileUtil::Exists(raw_path) && !FileUtil::IsDirectory(raw_path))
356 FileUtil::Delete(raw_path);
357
358 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH;
359
360 if (!FileUtil::CreateFullPath(path)) {
361 LOG_WARNING(Service_Mii,
362 "Failed to create full path of MiiDatabase.dat. Create the directory "
363 "nand/system/save/8000000000000030 to mitigate this "
364 "issue.");
365 return;
366 }
367
368 FileUtil::IOFile save(path, "wb");
369
370 if (!save.IsOpen()) {
371 LOG_WARNING(Service_Mii, "Failed to write save data to file... No changes to user data "
372 "made in current session will be saved.");
373 return;
374 }
375
376 save.Resize(sizeof(MiiDatabase));
377 if (save.WriteBytes(&database, sizeof(MiiDatabase)) != sizeof(MiiDatabase)) {
378 LOG_WARNING(Service_Mii, "Failed to write all data to save file... Data may be malformed "
379 "and/or regenerated on next run.");
380 save.Resize(0);
381 }
382}
383
384void MiiManager::ReadFromFile() {
385 FileUtil::IOFile save(
386 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH, "rb");
387
388 if (!save.IsOpen()) {
389 LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new "
390 "blank Mii database with no Miis.");
391 std::memcpy(&database, &DEFAULT_MII_DATABASE, sizeof(MiiDatabase));
392 return;
393 }
394
395 if (save.ReadBytes(&database, sizeof(MiiDatabase)) != sizeof(MiiDatabase)) {
396 LOG_WARNING(Service_ACC, "MiiDatabase.dat is smaller than expected... Generating new blank "
397 "Mii database with no Miis.");
398 std::memcpy(&database, &DEFAULT_MII_DATABASE, sizeof(MiiDatabase));
399 return;
400 }
401
402 EnsureDatabasePartition();
403}
404
405MiiStoreData MiiManager::CreateMiiWithUniqueUUID() const {
406 auto new_mii = DEFAULT_MII;
407
408 do {
409 new_mii.uuid = Common::UUID::Generate();
410 } while (IndexOf(new_mii.uuid) != INVALID_INDEX);
411
412 return new_mii;
413}
414
415void MiiManager::EnsureDatabasePartition() {
416 std::stable_partition(database.miis.begin(), database.miis.end(),
417 [](const MiiStoreData& elem) { return elem.uuid; });
418}
419
420} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
deleted file mode 100644
index fc742816a..000000000
--- a/src/core/hle/service/mii/mii_manager.h
+++ /dev/null
@@ -1,273 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/bit_field.h"
8#include "common/common_funcs.h"
9#include "common/uuid.h"
10
11namespace Service::Mii {
12
13constexpr std::size_t MAX_MIIS{100};
14constexpr u32 INVALID_INDEX{0xFFFFFFFF};
15
16struct RandomParameters {
17 u32 unknown_1{};
18 u32 unknown_2{};
19 u32 unknown_3{};
20};
21static_assert(sizeof(RandomParameters) == 0xC, "RandomParameters has incorrect size.");
22
23enum class Source : u32 {
24 Database = 0,
25 Default = 1,
26 Account = 2,
27 Friend = 3,
28};
29
30std::ostream& operator<<(std::ostream& os, Source source);
31
32struct MiiInfo {
33 Common::UUID uuid{Common::INVALID_UUID};
34 std::array<char16_t, 11> name{};
35 u8 font_region{};
36 u8 favorite_color{};
37 u8 gender{};
38 u8 height{};
39 u8 weight{};
40 u8 mii_type{};
41 u8 mii_region{};
42 u8 face_type{};
43 u8 face_color{};
44 u8 face_wrinkle{};
45 u8 face_makeup{};
46 u8 hair_type{};
47 u8 hair_color{};
48 bool hair_flip{};
49 u8 eye_type{};
50 u8 eye_color{};
51 u8 eye_scale{};
52 u8 eye_aspect_ratio{};
53 u8 eye_rotate{};
54 u8 eye_x{};
55 u8 eye_y{};
56 u8 eyebrow_type{};
57 u8 eyebrow_color{};
58 u8 eyebrow_scale{};
59 u8 eyebrow_aspect_ratio{};
60 u8 eyebrow_rotate{};
61 u8 eyebrow_x{};
62 u8 eyebrow_y{};
63 u8 nose_type{};
64 u8 nose_scale{};
65 u8 nose_y{};
66 u8 mouth_type{};
67 u8 mouth_color{};
68 u8 mouth_scale{};
69 u8 mouth_aspect_ratio{};
70 u8 mouth_y{};
71 u8 facial_hair_color{};
72 u8 beard_type{};
73 u8 mustache_type{};
74 u8 mustache_scale{};
75 u8 mustache_y{};
76 u8 glasses_type{};
77 u8 glasses_color{};
78 u8 glasses_scale{};
79 u8 glasses_y{};
80 u8 mole_type{};
81 u8 mole_scale{};
82 u8 mole_x{};
83 u8 mole_y{};
84 INSERT_PADDING_BYTES(1);
85
86 std::u16string Name() const;
87};
88static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
89static_assert(std::has_unique_object_representations_v<MiiInfo>,
90 "All bits of MiiInfo must contribute to its value.");
91
92bool operator==(const MiiInfo& lhs, const MiiInfo& rhs);
93bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs);
94
95#pragma pack(push, 4)
96struct MiiInfoElement {
97 MiiInfo info{};
98 Source source{};
99};
100static_assert(sizeof(MiiInfoElement) == 0x5C, "MiiInfoElement has incorrect size.");
101
102struct MiiStoreBitFields {
103 union {
104 u32 word_0{};
105
106 BitField<24, 8, u32> hair_type;
107 BitField<23, 1, u32> mole_type;
108 BitField<16, 7, u32> height;
109 BitField<15, 1, u32> hair_flip;
110 BitField<8, 7, u32> weight;
111 BitField<0, 7, u32> hair_color;
112 };
113
114 union {
115 u32 word_1{};
116
117 BitField<31, 1, u32> gender;
118 BitField<24, 7, u32> eye_color;
119 BitField<16, 7, u32> eyebrow_color;
120 BitField<8, 7, u32> mouth_color;
121 BitField<0, 7, u32> facial_hair_color;
122 };
123
124 union {
125 u32 word_2{};
126
127 BitField<31, 1, u32> mii_type;
128 BitField<24, 7, u32> glasses_color;
129 BitField<22, 2, u32> font_region;
130 BitField<16, 6, u32> eye_type;
131 BitField<14, 2, u32> mii_region;
132 BitField<8, 6, u32> mouth_type;
133 BitField<5, 3, u32> glasses_scale;
134 BitField<0, 5, u32> eye_y;
135 };
136
137 union {
138 u32 word_3{};
139
140 BitField<29, 3, u32> mustache_type;
141 BitField<24, 5, u32> eyebrow_type;
142 BitField<21, 3, u32> beard_type;
143 BitField<16, 5, u32> nose_type;
144 BitField<13, 3, u32> mouth_aspect;
145 BitField<8, 5, u32> nose_y;
146 BitField<5, 3, u32> eyebrow_aspect;
147 BitField<0, 5, u32> mouth_y;
148 };
149
150 union {
151 u32 word_4{};
152
153 BitField<29, 3, u32> eye_rotate;
154 BitField<24, 5, u32> mustache_y;
155 BitField<21, 3, u32> eye_aspect;
156 BitField<16, 5, u32> glasses_y;
157 BitField<13, 3, u32> eye_scale;
158 BitField<8, 5, u32> mole_x;
159 BitField<0, 5, u32> mole_y;
160 };
161
162 union {
163 u32 word_5{};
164
165 BitField<24, 5, u32> glasses_type;
166 BitField<20, 4, u32> face_type;
167 BitField<16, 4, u32> favorite_color;
168 BitField<12, 4, u32> face_wrinkle;
169 BitField<8, 4, u32> face_color;
170 BitField<4, 4, u32> eye_x;
171 BitField<0, 4, u32> face_makeup;
172 };
173
174 union {
175 u32 word_6{};
176
177 BitField<28, 4, u32> eyebrow_rotate;
178 BitField<24, 4, u32> eyebrow_scale;
179 BitField<20, 4, u32> eyebrow_y;
180 BitField<16, 4, u32> eyebrow_x;
181 BitField<12, 4, u32> mouth_scale;
182 BitField<8, 4, u32> nose_scale;
183 BitField<4, 4, u32> mole_scale;
184 BitField<0, 4, u32> mustache_scale;
185 };
186};
187static_assert(sizeof(MiiStoreBitFields) == 0x1C, "MiiStoreBitFields has incorrect size.");
188static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
189 "MiiStoreBitFields is not trivially copyable.");
190
191struct MiiStoreData {
192 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
193 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
194 // not suitable for our uses.
195 std::array<u8, 0x1C> data{};
196 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
197
198 std::array<char16_t, 10> name{};
199 Common::UUID uuid{Common::INVALID_UUID};
200 u16 crc_1{};
201 u16 crc_2{};
202
203 std::u16string Name() const;
204};
205static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
206
207struct MiiStoreDataElement {
208 MiiStoreData data{};
209 Source source{};
210};
211static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
212
213struct MiiDatabase {
214 u32 magic{}; // 'NFDB'
215 std::array<MiiStoreData, MAX_MIIS> miis{};
216 INSERT_PADDING_BYTES(1);
217 u8 count{};
218 u16 crc{};
219};
220static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
221#pragma pack(pop)
222
223// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
224// with providing an easy interface for HLE emulation of the mii service.
225class MiiManager {
226public:
227 MiiManager();
228 ~MiiManager();
229
230 MiiInfo CreateRandom(RandomParameters params);
231 MiiInfo CreateDefault(u32 index);
232
233 bool CheckUpdatedFlag() const;
234 void ResetUpdatedFlag();
235
236 bool IsTestModeEnabled() const;
237
238 bool Empty() const;
239 bool Full() const;
240
241 void Clear();
242
243 u32 Size() const;
244
245 MiiInfo GetInfo(u32 index) const;
246 MiiInfoElement GetInfoElement(u32 index) const;
247 MiiStoreData GetStoreData(u32 index) const;
248 MiiStoreDataElement GetStoreDataElement(u32 index) const;
249
250 bool Remove(Common::UUID uuid);
251 u32 IndexOf(Common::UUID uuid) const;
252 u32 IndexOf(const MiiInfo& info) const;
253
254 bool Move(Common::UUID uuid, u32 new_index);
255 bool AddOrReplace(const MiiStoreData& data);
256
257 bool DestroyFile();
258 bool DeleteFile();
259
260private:
261 void WriteToFile();
262 void ReadFromFile();
263
264 MiiStoreData CreateMiiWithUniqueUUID() const;
265
266 void EnsureDatabasePartition();
267
268 MiiDatabase database;
269 bool updated_flag{};
270 bool is_test_mode_enabled{};
271};
272
273}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.cpp b/src/core/hle/service/mii/raw_data.cpp
new file mode 100644
index 000000000..25d7bae0c
--- /dev/null
+++ b/src/core/hle/service/mii/raw_data.cpp
@@ -0,0 +1,2261 @@
1// MIT License
2//
3// Copyright (c) Ryujinx Team and Contributors
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6// associated documentation files (the "Software"), to deal in the Software without restriction,
7// including without limitation the rights to use, copy, modify, merge, publish, distribute,
8// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in all copies or
12// substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19//
20
21#include "core/hle/service/mii/raw_data.h"
22
23namespace Service::Mii::RawData {
24
25const std::array<u8, 1728> DefaultMii{
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
29 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
30 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
31 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
32 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
33 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
36 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
42 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
44 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
45 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
50 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
56 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
58 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
59 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
60 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
63 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
66 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
69 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
70 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
71 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
72 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
77 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
79 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
83 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
84 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
85 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
86 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
87 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
90 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
93 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
96 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
98 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
99 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
104 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
106 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x0e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
109 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
110 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
111 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
112 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
113 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
114 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
117 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
118 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
120 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
123 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
125 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
126 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
131 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
133 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
134
135const std::array<u8, 3672> RandomMiiFaceline{
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
138 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
139 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
151 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
152 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
164 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
175 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
176 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
177 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
178 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
189 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
190 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
191 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
202 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
203 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
215 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
216 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
226 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
227 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
228 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
229 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
240 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
241 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
253 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
254 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
266 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
278 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
279 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
291 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
292 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
302 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
304 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
305 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
315 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
317 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
318 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
328 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
330 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
331 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
342 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
343 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
353 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
355 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
356 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
366
367const std::array<u8, 1200> RandomMiiFacelineColor{
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
369 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
370 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
371 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
381 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
383 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
395 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
396 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
407 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
408 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
421 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
431 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
443
444const std::array<u8, 3672> RandomMiiFacelineWrinkle{
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
484 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
487 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
488 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
489 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
500 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
501 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
513 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
514 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
523 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
524 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
525 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
526 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
527 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
535 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
536 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
537 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
538 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
539 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
540 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
548 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
549 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
550 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
551 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
552 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
603 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
611 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
616 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
624 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
629 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
637 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
638 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
639 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
640 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
641 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
642 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
650 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
651 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
652 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
653 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
654 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
662 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
663 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
664 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
665 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
666 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
667 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
675
676const std::array<u8, 3672> RandomMiiFacelineMakeup{
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
695 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
716 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
721 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
759 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
767 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
772 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
797 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
808 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
809 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
810 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
821 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
822 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
823 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
834 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
835 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
843 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
845 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
846 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
847 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
848 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
856 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
859 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
860 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
861 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
869 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
872 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
873 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
874 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
885 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
886 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
894 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
898 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
899 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
907
908const std::array<u8, 3672> RandomMiiHairType{
909 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
910 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
911 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
912 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
913 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
914 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
915 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
916 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
917 0x56, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
923 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
924 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
925 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
926 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
927 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
928 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
929 0x42, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
930 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
934 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
935 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
936 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
937 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
938 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
939 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
940 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
941 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
942 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
943 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
948 0x26, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
949 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
950 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
951 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
952 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
953 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
954 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
955 0x3c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
956 0x43, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
957 0x4c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
958 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
961 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
962 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
963 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
964 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
965 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
966 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
967 0x38, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
968 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
969 0x44, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
970 0x51, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
974 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
975 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
976 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
977 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
978 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
979 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
980 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
981 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
982 0x46, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
983 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
987 0x1e, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
988 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
989 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
990 0x41, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
995 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
997 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
999 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
1000 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1001 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1002 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
1003 0x41, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1012 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1013 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1014 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1015 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
1016 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1026 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1027 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1028 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1029 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1030 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1031 0x1c, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
1032 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
1033 0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
1034 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1037 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1038 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1039 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1040 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1041 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1042 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1043 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1044 0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
1045 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1046 0x4a, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
1047 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1049 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1050 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1051 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1052 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1053 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1054 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1055 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1056 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1057 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
1058 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
1059 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
1060 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1062 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1063 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1064 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1065 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1066 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1067 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1068 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1069 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1070 0x2a, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1071 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
1072 0x47, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
1073 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1075 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1076 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1077 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1078 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1079 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1080 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1081 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1082 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
1083 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
1084 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1085 0x4a, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
1086 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1088 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1089 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1090 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1091 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1092 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1093 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1094 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1095 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1096 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1097 0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
1098 0x4f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
1099 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1101 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1102 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1103 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1104 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1105 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1106 0x3a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1107 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1113 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1115 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1116 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1117 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1118 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1119 0x3e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1120 0x51, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1126 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1128 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1129 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1130 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1131 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
1132 0x45, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
1133 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1139
1140const std::array<u8, 1800> RandomMiiHairColor{
1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1154 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1168 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1169 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1170 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1171 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1179 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1180 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1181 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1182 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1183 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1184 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1192 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1193 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1194 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1195 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1196 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1204 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1205 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1206 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1207 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1208 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1209 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1221 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1229 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1231 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1232 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1233 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1234 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1242 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1244 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1245 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1246 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1254
1255const std::array<u8, 3672> RandomMiiEyeType{
1256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1257 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1258 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1259 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1260 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1261 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1262 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1263 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1270 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1271 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1272 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1273 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1274 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1275 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1276 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1283 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1284 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1285 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1286 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1287 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1288 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1289 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1295 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1296 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1297 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1298 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1299 0x16, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
1300 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1302 0x2c, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1303 0x35, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1308 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1309 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1310 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1311 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1312 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1313 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1314 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1315 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1316 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1321 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1322 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1323 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1324 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1325 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1326 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1327 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1328 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1329 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1334 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1335 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1336 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1337 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1338 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1339 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1340 0x35, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1346 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1347 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1348 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1349 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1350 0x16, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1351 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1352 0x2c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1353 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1358 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
1359 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1360 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1361 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1362 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1363 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1364 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1365 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1366 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1372 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1373 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1374 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1375 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1376 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1377 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1378 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1379 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1380 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1381 0x39, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1385 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1386 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1387 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1388 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1389 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1390 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1391 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1392 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1393 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1394 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1398 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1399 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1400 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1401 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1402 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1403 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1404 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1405 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1406 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1407 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1409 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1410 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1411 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1412 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1413 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1414 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1415 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1416 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1417 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1418 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1419 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1420 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1421 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1422 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1424 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1425 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1426 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1427 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1428 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1429 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1430 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1431 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
1432 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1433 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1434 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1435 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1436 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1437 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1438 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1439 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1440 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1441 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1442 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1443 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1444 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1445 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1446 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
1447 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1448 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1449 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1450 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1451 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1452 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1453 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1454 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1455 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
1456 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1460 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1461 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1462 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1463 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1464 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1465 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1466 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1467 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1468 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1469 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1473 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1474 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1475 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1476 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1477 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1478 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1479 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1480 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1481 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1482 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1486
1487const std::array<u8, 588> RandomMiiEyeColor{
1488 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1500 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1501 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1502 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1503 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1515 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1525
1526const std::array<u8, 3672> RandomMiiEyebrowType{
1527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1528 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1529 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1530 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1531 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1532 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1540 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1541 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1542 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1543 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1544 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1545 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1553 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1554 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1555 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1556 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1557 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1566 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1567 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1568 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1569 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1570 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1571 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1578 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1579 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1580 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1581 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1582 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1583 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1584 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1591 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1592 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1593 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1594 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1595 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1596 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1597 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1604 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1605 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1606 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1607 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1608 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1609 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1617 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1618 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1619 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1620 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1621 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1622 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1629 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1630 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1631 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1632 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1633 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1634 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1635 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1643 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1644 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1656 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1657 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1667 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1668 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1669 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1670 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1681 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1682 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1683 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1693 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1694 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1695 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1696 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1706 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1707 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1708 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1709 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1718 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1719 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1720 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1721 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1731 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1732 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1733 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1734 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1744 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1745 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1746 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1757
1758const std::array<u8, 3672> RandomMiiNoseType{
1759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1760 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1761 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1762 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1772 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1773 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1774 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1775 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1785 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1786 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1787 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1788 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1798 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1799 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1800 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1801 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1802 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1811 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1812 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1813 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1814 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1815 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1823 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1824 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1825 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1826 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1827 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1836 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1837 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1838 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1839 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1840 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1849 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1850 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1851 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1852 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1853 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1861 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1862 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1863 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1864 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1865 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1875 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1876 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1885 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1886 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1887 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1888 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1889 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1894 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1899 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1901 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1902 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1908 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1909 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1910 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1912 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1913 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1914 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1915 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1917 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1922 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1924 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1925 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1926 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1927 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1928 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1933 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1934 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1935 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1936 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1937 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1938 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1939 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1940 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1942 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1943 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1948 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1950 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1951 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1952 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1953 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1954 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1956 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1958 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1963 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1964 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1965 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1966 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1967 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1970 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1975 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1976 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1977 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1978 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1979 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1980 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1989
1990const std::array<u8, 3672> RandomMiiMouthType{
1991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1992 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1993 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1994 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1995 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1996 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1997 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1998 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2000 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2001 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2004 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2005 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2006 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
2007 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2008 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2009 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2010 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2011 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2017 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2018 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2019 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2020 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2021 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2022 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
2023 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2024 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2025 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2026 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2030 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2031 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2032 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2033 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2034 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2035 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
2036 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2037 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2042 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2043 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2044 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
2045 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2046 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2047 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2048 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2049 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2052 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2055 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2056 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2057 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
2058 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2059 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2060 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2061 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
2062 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2063 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2065 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2068 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2069 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2070 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2071 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2072 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2073 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2074 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2080 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2081 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2082 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2083 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
2084 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2085 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2086 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2087 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2089 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2094 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2095 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
2096 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2097 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2098 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2099 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2100 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2107 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2108 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2109 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2110 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2111 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2112 0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
2113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2119 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2120 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
2121 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2122 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2123 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2124 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2125 0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
2126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2131 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2132 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2133 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2134 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2135 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2136 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2137 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
2138 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2144 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2145 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2146 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2147 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2148 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2149 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
2150 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2151 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2157 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2158 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2159 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2160 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2161 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2162 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
2163 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2164 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2170 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2171 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
2172 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2173 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2174 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2175 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2176 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2182 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2183 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2184 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2185 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2186 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2187 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2188 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2189 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2195 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2196 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2197 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2198 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
2199 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2200 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2201 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2202 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2208 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2209 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2210 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2211 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2212 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2213 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2214 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2221
2222const std::array<u8, 588> RandomMiiGlassType{
2223 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
2224 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2235 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
2236 0x56, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
2237 0x60, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2248 0x4e, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
2249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2260
2261} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
new file mode 100644
index 000000000..a02a5c0fd
--- /dev/null
+++ b/src/core/hle/service/mii/raw_data.h
@@ -0,0 +1,27 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/common_types.h"
10
11namespace Service::Mii::RawData {
12
13extern const std::array<u8, 1728> DefaultMii;
14extern const std::array<u8, 3672> RandomMiiFaceline;
15extern const std::array<u8, 1200> RandomMiiFacelineColor;
16extern const std::array<u8, 3672> RandomMiiFacelineWrinkle;
17extern const std::array<u8, 3672> RandomMiiFacelineMakeup;
18extern const std::array<u8, 3672> RandomMiiHairType;
19extern const std::array<u8, 1800> RandomMiiHairColor;
20extern const std::array<u8, 3672> RandomMiiEyeType;
21extern const std::array<u8, 588> RandomMiiEyeColor;
22extern const std::array<u8, 3672> RandomMiiEyebrowType;
23extern const std::array<u8, 3672> RandomMiiNoseType;
24extern const std::array<u8, 3672> RandomMiiMouthType;
25extern const std::array<u8, 588> RandomMiiGlassType;
26
27} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
new file mode 100644
index 000000000..d65a1055e
--- /dev/null
+++ b/src/core/hle/service/mii/types.h
@@ -0,0 +1,67 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9
10namespace Service::Mii {
11
12enum class Age : u32 {
13 Young,
14 Normal,
15 Old,
16 All,
17};
18
19enum class BeardType : u32 {
20 None,
21 Beard1,
22 Beard2,
23 Beard3,
24 Beard4,
25 Beard5,
26};
27
28enum class BeardAndMustacheFlag : u32 { Beard = 1, Mustache, All = Beard | Mustache };
29DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
30
31enum class FontRegion : u32 {
32 Standard,
33 China,
34 Korea,
35 Taiwan,
36};
37
38enum class Gender : u32 {
39 Male,
40 Female,
41 All,
42 Maximum = Female,
43};
44
45enum class HairFlip : u32 {
46 Left,
47 Right,
48 Maximum = Right,
49};
50
51enum class MustacheType : u32 {
52 None,
53 Mustache1,
54 Mustache2,
55 Mustache3,
56 Mustache4,
57 Mustache5,
58};
59
60enum class Race : u32 {
61 Black,
62 White,
63 Asian,
64 All,
65};
66
67} // namespace Service::Mii
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp
index fb9f36bfd..2e7da23fe 100644
--- a/src/core/memory/dmnt_cheat_vm.cpp
+++ b/src/core/memory/dmnt_cheat_vm.cpp
@@ -190,6 +190,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode& opcode) {
190 callbacks->CommandLog( 190 callbacks->CommandLog(
191 fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); 191 fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i]));
192 } 192 }
193 } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&opcode.opcode)) {
194 callbacks->CommandLog("Opcode: Read/Write Static Register");
195 if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
196 callbacks->CommandLog("Op Type: ReadStaticRegister");
197 } else {
198 callbacks->CommandLog("Op Type: WriteStaticRegister");
199 }
200 callbacks->CommandLog(fmt::format("Reg Idx {:X}", rw_static_reg->idx));
201 callbacks->CommandLog(fmt::format("Stc Idx {:X}", rw_static_reg->static_idx));
193 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { 202 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) {
194 callbacks->CommandLog("Opcode: Debug Log"); 203 callbacks->CommandLog("Opcode: Debug Log");
195 callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); 204 callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width));
@@ -544,6 +553,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
544 } 553 }
545 opcode.opcode = save_restore_regmask; 554 opcode.opcode = save_restore_regmask;
546 } break; 555 } break;
556 case CheatVmOpcodeType::ReadWriteStaticRegister: {
557 ReadWriteStaticRegisterOpcode rw_static_reg{};
558 // C3000XXx
559 // C3 = opcode 0xC3.
560 // XX = static register index.
561 // x = register index.
562 rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF);
563 rw_static_reg.idx = (first_dword & 0xF);
564 opcode.opcode = rw_static_reg;
565 } break;
547 case CheatVmOpcodeType::DebugLog: { 566 case CheatVmOpcodeType::DebugLog: {
548 DebugLogOpcode debug_log{}; 567 DebugLogOpcode debug_log{};
549 // FFFTIX## 568 // FFFTIX##
@@ -667,6 +686,7 @@ void DmntCheatVm::ResetState() {
667 registers.fill(0); 686 registers.fill(0);
668 saved_values.fill(0); 687 saved_values.fill(0);
669 loop_tops.fill(0); 688 loop_tops.fill(0);
689 static_registers.fill(0);
670 instruction_ptr = 0; 690 instruction_ptr = 0;
671 condition_depth = 0; 691 condition_depth = 0;
672 decode_success = true; 692 decode_success = true;
@@ -1153,6 +1173,15 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1153 } 1173 }
1154 } 1174 }
1155 } 1175 }
1176 } else if (auto rw_static_reg =
1177 std::get_if<ReadWriteStaticRegisterOpcode>(&cur_opcode.opcode)) {
1178 if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
1179 // Load a register with a static register.
1180 registers[rw_static_reg->idx] = static_registers[rw_static_reg->static_idx];
1181 } else {
1182 // Store a register to a static register.
1183 static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx];
1184 }
1156 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { 1185 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) {
1157 // Read value from memory. 1186 // Read value from memory.
1158 u64 log_value = 0; 1187 u64 log_value = 0;
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h
index 8351fd798..21b86b72c 100644
--- a/src/core/memory/dmnt_cheat_vm.h
+++ b/src/core/memory/dmnt_cheat_vm.h
@@ -56,6 +56,7 @@ enum class CheatVmOpcodeType : u32 {
56 BeginRegisterConditionalBlock = 0xC0, 56 BeginRegisterConditionalBlock = 0xC0,
57 SaveRestoreRegister = 0xC1, 57 SaveRestoreRegister = 0xC1,
58 SaveRestoreRegisterMask = 0xC2, 58 SaveRestoreRegisterMask = 0xC2,
59 ReadWriteStaticRegister = 0xC3,
59 60
60 // This is a meta entry, and not a real opcode. 61 // This is a meta entry, and not a real opcode.
61 // This is to facilitate multi-nybble instruction decoding. 62 // This is to facilitate multi-nybble instruction decoding.
@@ -237,6 +238,11 @@ struct SaveRestoreRegisterMaskOpcode {
237 std::array<bool, 0x10> should_operate{}; 238 std::array<bool, 0x10> should_operate{};
238}; 239};
239 240
241struct ReadWriteStaticRegisterOpcode {
242 u32 static_idx{};
243 u32 idx{};
244};
245
240struct DebugLogOpcode { 246struct DebugLogOpcode {
241 u32 bit_width{}; 247 u32 bit_width{};
242 u32 log_id{}; 248 u32 log_id{};
@@ -259,7 +265,8 @@ struct CheatVmOpcode {
259 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, 265 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode,
260 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, 266 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode,
261 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, 267 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode,
262 SaveRestoreRegisterMaskOpcode, DebugLogOpcode, UnrecognizedInstruction> 268 SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode,
269 UnrecognizedInstruction>
263 opcode{}; 270 opcode{};
264}; 271};
265 272
@@ -281,6 +288,10 @@ public:
281 288
282 static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; 289 static constexpr std::size_t MaximumProgramOpcodeCount = 0x400;
283 static constexpr std::size_t NumRegisters = 0x10; 290 static constexpr std::size_t NumRegisters = 0x10;
291 static constexpr std::size_t NumReadableStaticRegisters = 0x80;
292 static constexpr std::size_t NumWritableStaticRegisters = 0x80;
293 static constexpr std::size_t NumStaticRegisters =
294 NumReadableStaticRegisters + NumWritableStaticRegisters;
284 295
285 explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); 296 explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks);
286 ~DmntCheatVm(); 297 ~DmntCheatVm();
@@ -302,6 +313,7 @@ private:
302 std::array<u32, MaximumProgramOpcodeCount> program{}; 313 std::array<u32, MaximumProgramOpcodeCount> program{};
303 std::array<u64, NumRegisters> registers{}; 314 std::array<u64, NumRegisters> registers{};
304 std::array<u64, NumRegisters> saved_values{}; 315 std::array<u64, NumRegisters> saved_values{};
316 std::array<u64, NumStaticRegisters> static_registers{};
305 std::array<std::size_t, NumRegisters> loop_tops{}; 317 std::array<std::size_t, NumRegisters> loop_tops{};
306 318
307 bool DecodeNextOpcode(CheatVmOpcode& out); 319 bool DecodeNextOpcode(CheatVmOpcode& out);
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index d3886c4ec..44252dd81 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
5#include "common/file_util.h" 7#include "common/file_util.h"
6#include "core/core.h" 8#include "core/core.h"
7#include "core/gdbstub/gdbstub.h" 9#include "core/gdbstub/gdbstub.h"
@@ -65,18 +67,18 @@ Values values = {};
65bool configuring_global = true; 67bool configuring_global = true;
66 68
67std::string GetTimeZoneString() { 69std::string GetTimeZoneString() {
68 static constexpr std::array<const char*, 46> timezones{{ 70 static constexpr std::array timezones{
69 "auto", "default", "CET", "CST6CDT", "Cuba", "EET", "Egypt", "Eire", 71 "auto", "default", "CET", "CST6CDT", "Cuba", "EET", "Egypt", "Eire",
70 "EST", "EST5EDT", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0", 72 "EST", "EST5EDT", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0",
71 "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan", 73 "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan",
72 "Kwajalein", "Libya", "MET", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT", 74 "Kwajalein", "Libya", "MET", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT",
73 "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey", 75 "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey",
74 "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", 76 "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu",
75 }}; 77 };
76
77 ASSERT(Settings::values.time_zone_index.GetValue() < timezones.size());
78 78
79 return timezones[Settings::values.time_zone_index.GetValue()]; 79 const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue());
80 ASSERT(time_zone_index < timezones.size());
81 return timezones[time_zone_index];
80} 82}
81 83
82void Apply() { 84void Apply() {
@@ -91,41 +93,41 @@ void Apply() {
91 Service::HID::ReloadInputDevices(); 93 Service::HID::ReloadInputDevices();
92} 94}
93 95
94template <typename T>
95void LogSetting(const std::string& name, const T& value) {
96 LOG_INFO(Config, "{}: {}", name, value);
97}
98
99void LogSettings() { 96void LogSettings() {
97 const auto log_setting = [](std::string_view name, const auto& value) {
98 LOG_INFO(Config, "{}: {}", name, value);
99 };
100
100 LOG_INFO(Config, "yuzu Configuration:"); 101 LOG_INFO(Config, "yuzu Configuration:");
101 LogSetting("Controls_UseDockedMode", Settings::values.use_docked_mode); 102 log_setting("Controls_UseDockedMode", values.use_docked_mode);
102 LogSetting("System_RngSeed", Settings::values.rng_seed.GetValue().value_or(0)); 103 log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
103 LogSetting("System_CurrentUser", Settings::values.current_user); 104 log_setting("System_CurrentUser", values.current_user);
104 LogSetting("System_LanguageIndex", Settings::values.language_index.GetValue()); 105 log_setting("System_LanguageIndex", values.language_index.GetValue());
105 LogSetting("System_RegionIndex", Settings::values.region_index.GetValue()); 106 log_setting("System_RegionIndex", values.region_index.GetValue());
106 LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index.GetValue()); 107 log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue());
107 LogSetting("Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); 108 log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
108 LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor.GetValue()); 109 log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue());
109 LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue()); 110 log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue());
110 LogSetting("Renderer_FrameLimit", Settings::values.frame_limit.GetValue()); 111 log_setting("Renderer_FrameLimit", values.frame_limit.GetValue());
111 LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache.GetValue()); 112 log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
112 LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy.GetValue()); 113 log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
113 LogSetting("Renderer_UseAsynchronousGpuEmulation", 114 log_setting("Renderer_UseAsynchronousGpuEmulation",
114 Settings::values.use_asynchronous_gpu_emulation.GetValue()); 115 values.use_asynchronous_gpu_emulation.GetValue());
115 LogSetting("Renderer_UseVsync", Settings::values.use_vsync.GetValue()); 116 log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
116 LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders.GetValue()); 117 log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue());
117 LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy.GetValue()); 118 log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
118 LogSetting("Audio_OutputEngine", Settings::values.sink_id); 119 log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
119 LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching.GetValue()); 120 log_setting("Audio_OutputEngine", values.sink_id);
120 LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); 121 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
121 LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd); 122 log_setting("Audio_OutputDevice", values.audio_device_id);
122 LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); 123 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd);
123 LogSetting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); 124 log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir));
124 LogSetting("Debugging_UseGdbstub", Settings::values.use_gdbstub); 125 log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir));
125 LogSetting("Debugging_GdbstubPort", Settings::values.gdbstub_port); 126 log_setting("Debugging_UseGdbstub", values.use_gdbstub);
126 LogSetting("Debugging_ProgramArgs", Settings::values.program_args); 127 log_setting("Debugging_GdbstubPort", values.gdbstub_port);
127 LogSetting("Services_BCATBackend", Settings::values.bcat_backend); 128 log_setting("Debugging_ProgramArgs", values.program_args);
128 LogSetting("Services_BCATBoxcatLocal", Settings::values.bcat_boxcat_local); 129 log_setting("Services_BCATBackend", values.bcat_backend);
130 log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local);
129} 131}
130 132
131float Volume() { 133float Volume() {
@@ -169,6 +171,7 @@ void RestoreGlobalState() {
169 values.use_asynchronous_gpu_emulation.SetGlobal(true); 171 values.use_asynchronous_gpu_emulation.SetGlobal(true);
170 values.use_vsync.SetGlobal(true); 172 values.use_vsync.SetGlobal(true);
171 values.use_assembly_shaders.SetGlobal(true); 173 values.use_assembly_shaders.SetGlobal(true);
174 values.use_asynchronous_shaders.SetGlobal(true);
172 values.use_fast_gpu_time.SetGlobal(true); 175 values.use_fast_gpu_time.SetGlobal(true);
173 values.force_30fps_mode.SetGlobal(true); 176 values.force_30fps_mode.SetGlobal(true);
174 values.bg_red.SetGlobal(true); 177 values.bg_red.SetGlobal(true);
@@ -184,4 +187,9 @@ void RestoreGlobalState() {
184 values.sound_index.SetGlobal(true); 187 values.sound_index.SetGlobal(true);
185} 188}
186 189
190void Sanitize() {
191 values.use_asynchronous_gpu_emulation.SetValue(
192 values.use_asynchronous_gpu_emulation.GetValue() || values.use_multi_core.GetValue());
193}
194
187} // namespace Settings 195} // namespace Settings
diff --git a/src/core/settings.h b/src/core/settings.h
index 3eb336f75..386233fdf 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -434,6 +434,7 @@ struct Values {
434 Setting<bool> use_asynchronous_gpu_emulation; 434 Setting<bool> use_asynchronous_gpu_emulation;
435 Setting<bool> use_vsync; 435 Setting<bool> use_vsync;
436 Setting<bool> use_assembly_shaders; 436 Setting<bool> use_assembly_shaders;
437 Setting<bool> use_asynchronous_shaders;
437 Setting<bool> force_30fps_mode; 438 Setting<bool> force_30fps_mode;
438 Setting<bool> use_fast_gpu_time; 439 Setting<bool> use_fast_gpu_time;
439 440
@@ -526,4 +527,7 @@ void LogSettings();
526// Restore the global state of all applicable settings in the Values struct 527// Restore the global state of all applicable settings in the Values struct
527void RestoreGlobalState(); 528void RestoreGlobalState();
528 529
530// Fixes settings that are known to cause issues with the emulator
531void Sanitize();
532
529} // namespace Settings 533} // namespace Settings
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 78915e6db..5a30c75da 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -207,6 +207,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
207 AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); 207 AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue());
208 AddField(field_type, "Renderer_UseAssemblyShaders", 208 AddField(field_type, "Renderer_UseAssemblyShaders",
209 Settings::values.use_assembly_shaders.GetValue()); 209 Settings::values.use_assembly_shaders.GetValue());
210 AddField(field_type, "Renderer_UseAsynchronousShaders",
211 Settings::values.use_asynchronous_shaders.GetValue());
210 AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); 212 AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
211} 213}
212 214
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index 38210ffcb..898a278a9 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -25,6 +25,7 @@ Adapter::Adapter() {
25 LOG_INFO(Input, "GC Adapter Initialization started"); 25 LOG_INFO(Input, "GC Adapter Initialization started");
26 26
27 current_status = NO_ADAPTER_DETECTED; 27 current_status = NO_ADAPTER_DETECTED;
28 get_origin.fill(true);
28 29
29 const int init_res = libusb_init(&libusb_ctx); 30 const int init_res = libusb_init(&libusb_ctx);
30 if (init_res == LIBUSB_SUCCESS) { 31 if (init_res == LIBUSB_SUCCESS) {
@@ -36,13 +37,8 @@ Adapter::Adapter() {
36 37
37GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) { 38GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) {
38 GCPadStatus pad = {}; 39 GCPadStatus pad = {};
39 bool get_origin = false;
40 40
41 ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4); 41 ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
42 if (type != ControllerTypes::None) {
43 get_origin = true;
44 }
45
46 adapter_controllers_status[port] = type; 42 adapter_controllers_status[port] = type;
47 43
48 static constexpr std::array<PadButton, 8> b1_buttons{ 44 static constexpr std::array<PadButton, 8> b1_buttons{
@@ -58,6 +54,11 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
58 PadButton::PAD_TRIGGER_L, 54 PadButton::PAD_TRIGGER_L,
59 }; 55 };
60 56
57 if (adapter_controllers_status[port] == ControllerTypes::None && !get_origin[port]) {
58 // Controller may have been disconnected, recalibrate if reconnected.
59 get_origin[port] = true;
60 }
61
61 if (adapter_controllers_status[port] != ControllerTypes::None) { 62 if (adapter_controllers_status[port] != ControllerTypes::None) {
62 const u8 b1 = adapter_payload[1 + (9 * port) + 1]; 63 const u8 b1 = adapter_payload[1 + (9 * port) + 1];
63 const u8 b2 = adapter_payload[1 + (9 * port) + 2]; 64 const u8 b2 = adapter_payload[1 + (9 * port) + 2];
@@ -74,16 +75,22 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
74 } 75 }
75 } 76 }
76 77
77 if (get_origin) {
78 pad.button |= PAD_GET_ORIGIN;
79 }
80
81 pad.stick_x = adapter_payload[1 + (9 * port) + 3]; 78 pad.stick_x = adapter_payload[1 + (9 * port) + 3];
82 pad.stick_y = adapter_payload[1 + (9 * port) + 4]; 79 pad.stick_y = adapter_payload[1 + (9 * port) + 4];
83 pad.substick_x = adapter_payload[1 + (9 * port) + 5]; 80 pad.substick_x = adapter_payload[1 + (9 * port) + 5];
84 pad.substick_y = adapter_payload[1 + (9 * port) + 6]; 81 pad.substick_y = adapter_payload[1 + (9 * port) + 6];
85 pad.trigger_left = adapter_payload[1 + (9 * port) + 7]; 82 pad.trigger_left = adapter_payload[1 + (9 * port) + 7];
86 pad.trigger_right = adapter_payload[1 + (9 * port) + 8]; 83 pad.trigger_right = adapter_payload[1 + (9 * port) + 8];
84
85 if (get_origin[port]) {
86 origin_status[port].stick_x = pad.stick_x;
87 origin_status[port].stick_y = pad.stick_y;
88 origin_status[port].substick_x = pad.substick_x;
89 origin_status[port].substick_y = pad.substick_y;
90 origin_status[port].trigger_left = pad.trigger_left;
91 origin_status[port].trigger_right = pad.trigger_right;
92 get_origin[port] = false;
93 }
87 } 94 }
88 return pad; 95 return pad;
89} 96}
@@ -132,31 +139,31 @@ void Adapter::Read() {
132 for (std::size_t port = 0; port < pads.size(); ++port) { 139 for (std::size_t port = 0; port < pads.size(); ++port) {
133 pads[port] = GetPadStatus(port, adapter_payload_copy); 140 pads[port] = GetPadStatus(port, adapter_payload_copy);
134 if (DeviceConnected(port) && configuring) { 141 if (DeviceConnected(port) && configuring) {
135 if (pads[port].button != PAD_GET_ORIGIN) { 142 if (pads[port].button != 0) {
136 pad_queue[port].Push(pads[port]); 143 pad_queue[port].Push(pads[port]);
137 } 144 }
138 145
139 // Accounting for a threshold here because of some controller variance 146 // Accounting for a threshold here because of some controller variance
140 if (pads[port].stick_x > pads[port].MAIN_STICK_CENTER_X + pads[port].THRESHOLD || 147 if (pads[port].stick_x > origin_status[port].stick_x + pads[port].THRESHOLD ||
141 pads[port].stick_x < pads[port].MAIN_STICK_CENTER_X - pads[port].THRESHOLD) { 148 pads[port].stick_x < origin_status[port].stick_x - pads[port].THRESHOLD) {
142 pads[port].axis = GCAdapter::PadAxes::StickX; 149 pads[port].axis = GCAdapter::PadAxes::StickX;
143 pads[port].axis_value = pads[port].stick_x; 150 pads[port].axis_value = pads[port].stick_x;
144 pad_queue[port].Push(pads[port]); 151 pad_queue[port].Push(pads[port]);
145 } 152 }
146 if (pads[port].stick_y > pads[port].MAIN_STICK_CENTER_Y + pads[port].THRESHOLD || 153 if (pads[port].stick_y > origin_status[port].stick_y + pads[port].THRESHOLD ||
147 pads[port].stick_y < pads[port].MAIN_STICK_CENTER_Y - pads[port].THRESHOLD) { 154 pads[port].stick_y < origin_status[port].stick_y - pads[port].THRESHOLD) {
148 pads[port].axis = GCAdapter::PadAxes::StickY; 155 pads[port].axis = GCAdapter::PadAxes::StickY;
149 pads[port].axis_value = pads[port].stick_y; 156 pads[port].axis_value = pads[port].stick_y;
150 pad_queue[port].Push(pads[port]); 157 pad_queue[port].Push(pads[port]);
151 } 158 }
152 if (pads[port].substick_x > pads[port].C_STICK_CENTER_X + pads[port].THRESHOLD || 159 if (pads[port].substick_x > origin_status[port].substick_x + pads[port].THRESHOLD ||
153 pads[port].substick_x < pads[port].C_STICK_CENTER_X - pads[port].THRESHOLD) { 160 pads[port].substick_x < origin_status[port].substick_x - pads[port].THRESHOLD) {
154 pads[port].axis = GCAdapter::PadAxes::SubstickX; 161 pads[port].axis = GCAdapter::PadAxes::SubstickX;
155 pads[port].axis_value = pads[port].substick_x; 162 pads[port].axis_value = pads[port].substick_x;
156 pad_queue[port].Push(pads[port]); 163 pad_queue[port].Push(pads[port]);
157 } 164 }
158 if (pads[port].substick_y > pads[port].C_STICK_CENTER_Y + pads[port].THRESHOLD || 165 if (pads[port].substick_y > origin_status[port].substick_y + pads[port].THRESHOLD ||
159 pads[port].substick_y < pads[port].C_STICK_CENTER_Y - pads[port].THRESHOLD) { 166 pads[port].substick_y < origin_status[port].substick_y - pads[port].THRESHOLD) {
160 pads[port].axis = GCAdapter::PadAxes::SubstickY; 167 pads[port].axis = GCAdapter::PadAxes::SubstickY;
161 pads[port].axis_value = pads[port].substick_y; 168 pads[port].axis_value = pads[port].substick_y;
162 pad_queue[port].Push(pads[port]); 169 pad_queue[port].Push(pads[port]);
@@ -237,6 +244,9 @@ void Adapter::Setup() {
237 } 244 }
238 libusb_free_device_list(devices, 1); 245 libusb_free_device_list(devices, 1);
239 } 246 }
247 // Break out of the ScanThreadFunc() loop that is constantly looking for the device
248 // Assumes user has GC adapter plugged in before launch to use the adapter
249 detect_thread_running = false;
240} 250}
241 251
242bool Adapter::CheckDeviceAccess(libusb_device* device) { 252bool Adapter::CheckDeviceAccess(libusb_device* device) {
@@ -345,6 +355,7 @@ void Adapter::Reset() {
345 adapter_input_thread.join(); 355 adapter_input_thread.join();
346 356
347 adapter_controllers_status.fill(ControllerTypes::None); 357 adapter_controllers_status.fill(ControllerTypes::None);
358 get_origin.fill(true);
348 current_status = NO_ADAPTER_DETECTED; 359 current_status = NO_ADAPTER_DETECTED;
349 360
350 if (usb_adapter_handle) { 361 if (usb_adapter_handle) {
@@ -367,6 +378,7 @@ void Adapter::ResetDeviceType(std::size_t port) {
367} 378}
368 379
369void Adapter::BeginConfiguration() { 380void Adapter::BeginConfiguration() {
381 get_origin.fill(true);
370 for (auto& pq : pad_queue) { 382 for (auto& pq : pad_queue) {
371 pq.Clear(); 383 pq.Clear();
372 } 384 }
@@ -396,4 +408,25 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
396 return state; 408 return state;
397} 409}
398 410
411int Adapter::GetOriginValue(int port, int axis) const {
412 const auto& status = origin_status[port];
413
414 switch (static_cast<PadAxes>(axis)) {
415 case PadAxes::StickX:
416 return status.stick_x;
417 case PadAxes::StickY:
418 return status.stick_y;
419 case PadAxes::SubstickX:
420 return status.substick_x;
421 case PadAxes::SubstickY:
422 return status.substick_y;
423 case PadAxes::TriggerLeft:
424 return status.trigger_left;
425 case PadAxes::TriggerRight:
426 return status.trigger_right;
427 default:
428 return 0;
429 }
430}
431
399} // namespace GCAdapter 432} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index e2cdd6255..3586c8bda 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -17,12 +17,6 @@ struct libusb_device_handle;
17 17
18namespace GCAdapter { 18namespace GCAdapter {
19 19
20enum {
21 PAD_USE_ORIGIN = 0x0080,
22 PAD_GET_ORIGIN = 0x2000,
23 PAD_ERR_STATUS = 0x8000,
24};
25
26enum class PadButton { 20enum class PadButton {
27 PAD_BUTTON_LEFT = 0x0001, 21 PAD_BUTTON_LEFT = 0x0001,
28 PAD_BUTTON_RIGHT = 0x0002, 22 PAD_BUTTON_RIGHT = 0x0002,
@@ -109,6 +103,8 @@ public:
109 std::array<GCState, 4>& GetPadState(); 103 std::array<GCState, 4>& GetPadState();
110 const std::array<GCState, 4>& GetPadState() const; 104 const std::array<GCState, 4>& GetPadState() const;
111 105
106 int GetOriginValue(int port, int axis) const;
107
112private: 108private:
113 GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload); 109 GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
114 110
@@ -159,6 +155,8 @@ private:
159 155
160 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue; 156 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
161 std::array<GCState, 4> state; 157 std::array<GCState, 4> state;
158 std::array<bool, 4> get_origin;
159 std::array<GCPadStatus, 4> origin_status;
162}; 160};
163 161
164} // namespace GCAdapter 162} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index b20419ec3..96e22d3ad 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -38,18 +38,12 @@ public:
38 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_, 38 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
39 GCAdapter::Adapter* adapter) 39 GCAdapter::Adapter* adapter)
40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_), 40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
41 gcadapter(adapter) { 41 gcadapter(adapter), origin_value(adapter->GetOriginValue(port_, axis_)) {}
42 // L/R triggers range is only in positive direction beginning near 0
43 // 0.0 threshold equates to near half trigger press, but threshold accounts for variability.
44 if (axis > 3) {
45 threshold *= -0.5;
46 }
47 }
48 42
49 bool GetStatus() const override { 43 bool GetStatus() const override {
50 if (gcadapter->DeviceConnected(port)) { 44 if (gcadapter->DeviceConnected(port)) {
51 const float axis_value = 45 const float current_axis_value = gcadapter->GetPadState()[port].axes.at(axis);
52 (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 128.0f; 46 const float axis_value = (current_axis_value - origin_value) / 128.0f;
53 if (trigger_if_greater) { 47 if (trigger_if_greater) {
54 // TODO: Might be worthwile to set a slider for the trigger threshold. It is 48 // TODO: Might be worthwile to set a slider for the trigger threshold. It is
55 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick 49 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
@@ -66,6 +60,7 @@ private:
66 float threshold; 60 float threshold;
67 bool trigger_if_greater; 61 bool trigger_if_greater;
68 GCAdapter::Adapter* gcadapter; 62 GCAdapter::Adapter* gcadapter;
63 const float origin_value;
69}; 64};
70 65
71GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) 66GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
@@ -155,15 +150,18 @@ void GCButtonFactory::EndConfiguration() {
155class GCAnalog final : public Input::AnalogDevice { 150class GCAnalog final : public Input::AnalogDevice {
156public: 151public:
157 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter) 152 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter)
158 : 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),
154 origin_value_x(adapter->GetOriginValue(port_, axis_x_)),
155 origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {}
159 156
160 float GetAxis(int axis) const { 157 float GetAxis(int axis) const {
161 if (gcadapter->DeviceConnected(port)) { 158 if (gcadapter->DeviceConnected(port)) {
162 std::lock_guard lock{mutex}; 159 std::lock_guard lock{mutex};
160 const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
163 // division is not by a perfect 128 to account for some variance in center location 161 // division is not by a perfect 128 to account for some variance in center location
164 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range 162 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
165 // [20-230] 163 // [20-230]
166 return (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 95.0f; 164 return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f;
167 } 165 }
168 return 0.0f; 166 return 0.0f;
169 } 167 }
@@ -215,8 +213,10 @@ private:
215 const int axis_x; 213 const int axis_x;
216 const int axis_y; 214 const int axis_y;
217 const float deadzone; 215 const float deadzone;
218 mutable std::mutex mutex;
219 GCAdapter::Adapter* gcadapter; 216 GCAdapter::Adapter* gcadapter;
217 const float origin_value_x;
218 const float origin_value_y;
219 mutable std::mutex mutex;
220}; 220};
221 221
222/// An analog device factory that creates analog devices from GC Adapter 222/// An analog device factory that creates analog devices from GC Adapter
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 21c46a567..3cd896a0f 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -98,6 +98,8 @@ add_library(video_core STATIC
98 sampler_cache.cpp 98 sampler_cache.cpp
99 sampler_cache.h 99 sampler_cache.h
100 shader_cache.h 100 shader_cache.h
101 shader_notify.cpp
102 shader_notify.h
101 shader/decode/arithmetic.cpp 103 shader/decode/arithmetic.cpp
102 shader/decode/arithmetic_immediate.cpp 104 shader/decode/arithmetic_immediate.cpp
103 shader/decode/bfe.cpp 105 shader/decode/bfe.cpp
@@ -128,6 +130,8 @@ add_library(video_core STATIC
128 shader/decode/other.cpp 130 shader/decode/other.cpp
129 shader/ast.cpp 131 shader/ast.cpp
130 shader/ast.h 132 shader/ast.h
133 shader/async_shaders.cpp
134 shader/async_shaders.h
131 shader/compiler_settings.cpp 135 shader/compiler_settings.cpp
132 shader/compiler_settings.h 136 shader/compiler_settings.h
133 shader/control_flow.cpp 137 shader/control_flow.cpp
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 758bfe148..8e19c3373 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -20,6 +20,7 @@
20#include "video_core/gpu.h" 20#include "video_core/gpu.h"
21#include "video_core/memory_manager.h" 21#include "video_core/memory_manager.h"
22#include "video_core/renderer_base.h" 22#include "video_core/renderer_base.h"
23#include "video_core/shader_notify.h"
23#include "video_core/video_core.h" 24#include "video_core/video_core.h"
24 25
25namespace Tegra { 26namespace Tegra {
@@ -36,6 +37,7 @@ GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& render
36 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); 37 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
37 maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); 38 maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
38 kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); 39 kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
40 shader_notify = std::make_unique<VideoCore::ShaderNotify>();
39} 41}
40 42
41GPU::~GPU() = default; 43GPU::~GPU() = default;
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 2c42483bd..8d04d9fd9 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -33,6 +33,7 @@ class System;
33 33
34namespace VideoCore { 34namespace VideoCore {
35class RendererBase; 35class RendererBase;
36class ShaderNotify;
36} // namespace VideoCore 37} // namespace VideoCore
37 38
38namespace Tegra { 39namespace Tegra {
@@ -207,6 +208,14 @@ public:
207 return *renderer; 208 return *renderer;
208 } 209 }
209 210
211 VideoCore::ShaderNotify& ShaderNotify() {
212 return *shader_notify;
213 }
214
215 const VideoCore::ShaderNotify& ShaderNotify() const {
216 return *shader_notify;
217 }
218
210 // Waits for the GPU to finish working 219 // Waits for the GPU to finish working
211 virtual void WaitIdle() const = 0; 220 virtual void WaitIdle() const = 0;
212 221
@@ -347,6 +356,8 @@ private:
347 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; 356 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
348 /// Inline memory engine 357 /// Inline memory engine
349 std::unique_ptr<Engines::KeplerMemory> kepler_memory; 358 std::unique_ptr<Engines::KeplerMemory> kepler_memory;
359 /// Shader build notifier
360 std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
350 361
351 std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; 362 std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
352 363
diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h
index 4d00b84b0..31ee3440a 100644
--- a/src/video_core/macro/macro.h
+++ b/src/video_core/macro/macro.h
@@ -103,8 +103,9 @@ public:
103 virtual ~CachedMacro() = default; 103 virtual ~CachedMacro() = default;
104 /** 104 /**
105 * Executes the macro code with the specified input parameters. 105 * Executes the macro code with the specified input parameters.
106 * @param code The macro byte code to execute 106 *
107 * @param parameters The parameters of the macro 107 * @param parameters The parameters of the macro
108 * @param method The method to execute
108 */ 109 */
109 virtual void Execute(const std::vector<u32>& parameters, u32 method) = 0; 110 virtual void Execute(const std::vector<u32>& parameters, u32 method) = 0;
110}; 111};
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index 410f99018..0c9ff59a4 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -12,13 +12,11 @@ namespace Tegra {
12 12
13namespace { 13namespace {
14// HLE'd functions 14// HLE'd functions
15static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, 15void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
16 const std::vector<u32>& parameters) {
17 const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); 16 const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B);
18 17
19 maxwell3d.regs.draw.topology.Assign( 18 maxwell3d.regs.draw.topology.Assign(
20 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 19 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
21 ~(0x3ffffff << 26)));
22 maxwell3d.regs.vb_base_instance = parameters[5]; 20 maxwell3d.regs.vb_base_instance = parameters[5];
23 maxwell3d.mme_draw.instance_count = instance_count; 21 maxwell3d.mme_draw.instance_count = instance_count;
24 maxwell3d.regs.vb_element_base = parameters[3]; 22 maxwell3d.regs.vb_element_base = parameters[3];
@@ -33,8 +31,7 @@ static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d,
33 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 31 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
34} 32}
35 33
36static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, 34void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
37 const std::vector<u32>& parameters) {
38 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); 35 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
39 36
40 maxwell3d.regs.vertex_buffer.first = parameters[3]; 37 maxwell3d.regs.vertex_buffer.first = parameters[3];
@@ -52,8 +49,7 @@ static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d,
52 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 49 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
53} 50}
54 51
55static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, 52void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
56 const std::vector<u32>& parameters) {
57 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); 53 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
58 const u32 element_base = parameters[4]; 54 const u32 element_base = parameters[4];
59 const u32 base_instance = parameters[5]; 55 const u32 base_instance = parameters[5];
@@ -81,12 +77,12 @@ static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d,
81 maxwell3d.CallMethodFromMME(0x8e5, 0x0); 77 maxwell3d.CallMethodFromMME(0x8e5, 0x0);
82 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 78 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
83} 79}
84} // namespace 80} // Anonymous namespace
85 81
86constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{ 82constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{
87 std::make_pair<u64, HLEFunction>(0x771BB18C62444DA0, &HLE_771BB18C62444DA0), 83 {0x771BB18C62444DA0, &HLE_771BB18C62444DA0},
88 std::make_pair<u64, HLEFunction>(0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD), 84 {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD},
89 std::make_pair<u64, HLEFunction>(0x0217920100488FF7, &HLE_0217920100488FF7), 85 {0x0217920100488FF7, &HLE_0217920100488FF7},
90}}; 86}};
91 87
92HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} 88HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {}
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index c1f20f0ab..630acb73b 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -233,6 +233,8 @@ Device::Device()
233 GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && 233 GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 &&
234 GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; 234 GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2;
235 235
236 use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue();
237
236 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); 238 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
237 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); 239 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
238 LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); 240 LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug);
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index e1d811966..94d38d7d1 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -104,6 +104,10 @@ public:
104 return use_assembly_shaders; 104 return use_assembly_shaders;
105 } 105 }
106 106
107 bool UseAsynchronousShaders() const {
108 return use_asynchronous_shaders;
109 }
110
107private: 111private:
108 static bool TestVariableAoffi(); 112 static bool TestVariableAoffi();
109 static bool TestPreciseBug(); 113 static bool TestPreciseBug();
@@ -127,6 +131,7 @@ private:
127 bool has_fast_buffer_sub_data{}; 131 bool has_fast_buffer_sub_data{};
128 bool has_nv_viewport_array2{}; 132 bool has_nv_viewport_array2{};
129 bool use_assembly_shaders{}; 133 bool use_assembly_shaders{};
134 bool use_asynchronous_shaders{};
130}; 135};
131 136
132} // namespace OpenGL 137} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e960a0ef1..c3fad563c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -149,7 +149,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
149 shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, 149 shader_cache{*this, system, emu_window, device}, query_cache{system, *this},
150 buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, 150 buffer_cache{*this, system, device, STREAM_BUFFER_SIZE},
151 fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system}, 151 fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system},
152 screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker} { 152 screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker},
153 async_shaders{emu_window} {
153 CheckExtensions(); 154 CheckExtensions();
154 155
155 unified_uniform_buffer.Create(); 156 unified_uniform_buffer.Create();
@@ -162,6 +163,23 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
162 nullptr, 0); 163 nullptr, 0);
163 } 164 }
164 } 165 }
166
167 if (device.UseAsynchronousShaders()) {
168 // Max worker threads we should allow
169 constexpr auto MAX_THREADS = 2u;
170 // Amount of threads we should reserve for other parts of yuzu
171 constexpr auto RESERVED_THREADS = 6u;
172 // Get the amount of threads we can use(this can return zero)
173 const auto cpu_thread_count =
174 std::max(RESERVED_THREADS, std::thread::hardware_concurrency());
175 // Deduce how many "extra" threads we have to use.
176 const auto max_threads_unused = cpu_thread_count - RESERVED_THREADS;
177 // Always allow at least 1 thread regardless of our settings
178 const auto max_worker_count = std::max(1u, max_threads_unused);
179 // Don't use more than MAX_THREADS
180 const auto worker_count = std::min(max_worker_count, MAX_THREADS);
181 async_shaders.AllocateWorkers(worker_count);
182 }
165} 183}
166 184
167RasterizerOpenGL::~RasterizerOpenGL() { 185RasterizerOpenGL::~RasterizerOpenGL() {
@@ -336,7 +354,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
336 continue; 354 continue;
337 } 355 }
338 356
339 Shader* const shader = shader_cache.GetStageProgram(program); 357 Shader* shader = shader_cache.GetStageProgram(program, async_shaders);
340 358
341 if (device.UseAssemblyShaders()) { 359 if (device.UseAssemblyShaders()) {
342 // Check for ARB limitation. We only have 16 SSBOs per context state. To workaround this 360 // Check for ARB limitation. We only have 16 SSBOs per context state. To workaround this
@@ -353,7 +371,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
353 SetupDrawTextures(stage, shader); 371 SetupDrawTextures(stage, shader);
354 SetupDrawImages(stage, shader); 372 SetupDrawImages(stage, shader);
355 373
356 const GLuint program_handle = shader->GetHandle(); 374 const GLuint program_handle = shader->IsBuilt() ? shader->GetHandle() : 0;
357 switch (program) { 375 switch (program) {
358 case Maxwell::ShaderProgram::VertexA: 376 case Maxwell::ShaderProgram::VertexA:
359 case Maxwell::ShaderProgram::VertexB: 377 case Maxwell::ShaderProgram::VertexB:
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 4f082592f..a95646936 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -33,6 +33,7 @@
33#include "video_core/renderer_opengl/gl_state_tracker.h" 33#include "video_core/renderer_opengl/gl_state_tracker.h"
34#include "video_core/renderer_opengl/gl_texture_cache.h" 34#include "video_core/renderer_opengl/gl_texture_cache.h"
35#include "video_core/renderer_opengl/utils.h" 35#include "video_core/renderer_opengl/utils.h"
36#include "video_core/shader/async_shaders.h"
36#include "video_core/textures/texture.h" 37#include "video_core/textures/texture.h"
37 38
38namespace Core { 39namespace Core {
@@ -91,6 +92,14 @@ public:
91 return num_queued_commands > 0; 92 return num_queued_commands > 0;
92 } 93 }
93 94
95 VideoCommon::Shader::AsyncShaders& GetAsyncShaders() {
96 return async_shaders;
97 }
98
99 const VideoCommon::Shader::AsyncShaders& GetAsyncShaders() const {
100 return async_shaders;
101 }
102
94private: 103private:
95 /// Configures the color and depth framebuffer states. 104 /// Configures the color and depth framebuffer states.
96 void ConfigureFramebuffers(); 105 void ConfigureFramebuffers();
@@ -242,6 +251,7 @@ private:
242 ScreenInfo& screen_info; 251 ScreenInfo& screen_info;
243 ProgramManager& program_manager; 252 ProgramManager& program_manager;
244 StateTracker& state_tracker; 253 StateTracker& state_tracker;
254 VideoCommon::Shader::AsyncShaders async_shaders;
245 255
246 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 256 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
247 257
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index f8b322227..b05cb641c 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -177,6 +177,12 @@ public:
177 Release(); 177 Release();
178 } 178 }
179 179
180 OGLAssemblyProgram& operator=(OGLAssemblyProgram&& o) noexcept {
181 Release();
182 handle = std::exchange(o.handle, 0);
183 return *this;
184 }
185
180 /// Deletes the internal OpenGL resource 186 /// Deletes the internal OpenGL resource
181 void Release(); 187 void Release();
182 188
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index c6a3bf3a1..f469ed656 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -31,6 +31,7 @@
31#include "video_core/shader/registry.h" 31#include "video_core/shader/registry.h"
32#include "video_core/shader/shader_ir.h" 32#include "video_core/shader/shader_ir.h"
33#include "video_core/shader_cache.h" 33#include "video_core/shader_cache.h"
34#include "video_core/shader_notify.h"
34 35
35namespace OpenGL { 36namespace OpenGL {
36 37
@@ -140,9 +141,24 @@ std::shared_ptr<Registry> MakeRegistry(const ShaderDiskCacheEntry& entry) {
140 return registry; 141 return registry;
141} 142}
142 143
144std::unordered_set<GLenum> GetSupportedFormats() {
145 GLint num_formats;
146 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats);
147
148 std::vector<GLint> formats(num_formats);
149 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data());
150
151 std::unordered_set<GLenum> supported_formats;
152 for (const GLint format : formats) {
153 supported_formats.insert(static_cast<GLenum>(format));
154 }
155 return supported_formats;
156}
157
158} // Anonymous namespace
159
143ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier, 160ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier,
144 const ShaderIR& ir, const Registry& registry, 161 const ShaderIR& ir, const Registry& registry, bool hint_retrievable) {
145 bool hint_retrievable = false) {
146 const std::string shader_id = MakeShaderID(unique_identifier, shader_type); 162 const std::string shader_id = MakeShaderID(unique_identifier, shader_type);
147 LOG_INFO(Render_OpenGL, "{}", shader_id); 163 LOG_INFO(Render_OpenGL, "{}", shader_id);
148 164
@@ -181,30 +197,17 @@ ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 u
181 return program; 197 return program;
182} 198}
183 199
184std::unordered_set<GLenum> GetSupportedFormats() {
185 GLint num_formats;
186 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats);
187
188 std::vector<GLint> formats(num_formats);
189 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data());
190
191 std::unordered_set<GLenum> supported_formats;
192 for (const GLint format : formats) {
193 supported_formats.insert(static_cast<GLenum>(format));
194 }
195 return supported_formats;
196}
197
198} // Anonymous namespace
199
200Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_, 200Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_,
201 ProgramSharedPtr program_) 201 ProgramSharedPtr program_, bool is_built)
202 : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)} { 202 : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)},
203 is_built(is_built) {
203 handle = program->assembly_program.handle; 204 handle = program->assembly_program.handle;
204 if (handle == 0) { 205 if (handle == 0) {
205 handle = program->source_program.handle; 206 handle = program->source_program.handle;
206 } 207 }
207 ASSERT(handle != 0); 208 if (is_built) {
209 ASSERT(handle != 0);
210 }
208} 211}
209 212
210Shader::~Shader() = default; 213Shader::~Shader() = default;
@@ -214,42 +217,82 @@ GLuint Shader::GetHandle() const {
214 return handle; 217 return handle;
215} 218}
216 219
217std::unique_ptr<Shader> Shader::CreateStageFromMemory(const ShaderParameters& params, 220bool Shader::IsBuilt() const {
218 Maxwell::ShaderProgram program_type, 221 return is_built;
219 ProgramCode code, ProgramCode code_b) { 222}
223
224void Shader::AsyncOpenGLBuilt(OGLProgram new_program) {
225 program->source_program = std::move(new_program);
226 handle = program->source_program.handle;
227 is_built = true;
228}
229
230void Shader::AsyncGLASMBuilt(OGLAssemblyProgram new_program) {
231 program->assembly_program = std::move(new_program);
232 handle = program->assembly_program.handle;
233 is_built = true;
234}
235
236std::unique_ptr<Shader> Shader::CreateStageFromMemory(
237 const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode code,
238 ProgramCode code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr) {
220 const auto shader_type = GetShaderType(program_type); 239 const auto shader_type = GetShaderType(program_type);
221 const std::size_t size_in_bytes = code.size() * sizeof(u64); 240 const std::size_t size_in_bytes = code.size() * sizeof(u64);
222 241
223 auto registry = std::make_shared<Registry>(shader_type, params.system.GPU().Maxwell3D()); 242 auto& gpu = params.system.GPU();
224 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry); 243 gpu.ShaderNotify().MarkSharderBuilding();
225 // TODO(Rodrigo): Handle VertexA shaders 244
226 // std::optional<ShaderIR> ir_b; 245 auto registry = std::make_shared<Registry>(shader_type, gpu.Maxwell3D());
227 // if (!code_b.empty()) { 246 if (!async_shaders.IsShaderAsync(params.system.GPU()) ||
228 // ir_b.emplace(code_b, STAGE_MAIN_OFFSET); 247 !params.device.UseAsynchronousShaders()) {
229 // } 248 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
230 auto program = BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry); 249 // TODO(Rodrigo): Handle VertexA shaders
250 // std::optional<ShaderIR> ir_b;
251 // if (!code_b.empty()) {
252 // ir_b.emplace(code_b, STAGE_MAIN_OFFSET);
253 // }
254 auto program =
255 BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry);
256 ShaderDiskCacheEntry entry;
257 entry.type = shader_type;
258 entry.code = std::move(code);
259 entry.code_b = std::move(code_b);
260 entry.unique_identifier = params.unique_identifier;
261 entry.bound_buffer = registry->GetBoundBuffer();
262 entry.graphics_info = registry->GetGraphicsInfo();
263 entry.keys = registry->GetKeys();
264 entry.bound_samplers = registry->GetBoundSamplers();
265 entry.bindless_samplers = registry->GetBindlessSamplers();
266 params.disk_cache.SaveEntry(std::move(entry));
267
268 gpu.ShaderNotify().MarkShaderComplete();
269
270 return std::unique_ptr<Shader>(new Shader(std::move(registry),
271 MakeEntries(params.device, ir, shader_type),
272 std::move(program), true));
273 } else {
274 // Required for entries
275 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
276 auto entries = MakeEntries(params.device, ir, shader_type);
231 277
232 ShaderDiskCacheEntry entry; 278 async_shaders.QueueOpenGLShader(params.device, shader_type, params.unique_identifier,
233 entry.type = shader_type; 279 std::move(code), std::move(code_b), STAGE_MAIN_OFFSET,
234 entry.code = std::move(code); 280 COMPILER_SETTINGS, *registry, cpu_addr);
235 entry.code_b = std::move(code_b);
236 entry.unique_identifier = params.unique_identifier;
237 entry.bound_buffer = registry->GetBoundBuffer();
238 entry.graphics_info = registry->GetGraphicsInfo();
239 entry.keys = registry->GetKeys();
240 entry.bound_samplers = registry->GetBoundSamplers();
241 entry.bindless_samplers = registry->GetBindlessSamplers();
242 params.disk_cache.SaveEntry(std::move(entry));
243 281
244 return std::unique_ptr<Shader>(new Shader( 282 auto program = std::make_shared<ProgramHandle>();
245 std::move(registry), MakeEntries(params.device, ir, shader_type), std::move(program))); 283 return std::unique_ptr<Shader>(
284 new Shader(std::move(registry), std::move(entries), std::move(program), false));
285 }
246} 286}
247 287
248std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params, 288std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params,
249 ProgramCode code) { 289 ProgramCode code) {
250 const std::size_t size_in_bytes = code.size() * sizeof(u64); 290 const std::size_t size_in_bytes = code.size() * sizeof(u64);
251 291
252 auto& engine = params.system.GPU().KeplerCompute(); 292 auto& gpu = params.system.GPU();
293 gpu.ShaderNotify().MarkSharderBuilding();
294
295 auto& engine = gpu.KeplerCompute();
253 auto registry = std::make_shared<Registry>(ShaderType::Compute, engine); 296 auto registry = std::make_shared<Registry>(ShaderType::Compute, engine);
254 const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry); 297 const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
255 const u64 uid = params.unique_identifier; 298 const u64 uid = params.unique_identifier;
@@ -266,6 +309,8 @@ std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& p
266 entry.bindless_samplers = registry->GetBindlessSamplers(); 309 entry.bindless_samplers = registry->GetBindlessSamplers();
267 params.disk_cache.SaveEntry(std::move(entry)); 310 params.disk_cache.SaveEntry(std::move(entry));
268 311
312 gpu.ShaderNotify().MarkShaderComplete();
313
269 return std::unique_ptr<Shader>(new Shader(std::move(registry), 314 return std::unique_ptr<Shader>(new Shader(std::move(registry),
270 MakeEntries(params.device, ir, ShaderType::Compute), 315 MakeEntries(params.device, ir, ShaderType::Compute),
271 std::move(program))); 316 std::move(program)));
@@ -436,14 +481,51 @@ ProgramSharedPtr ShaderCacheOpenGL::GeneratePrecompiledProgram(
436 return program; 481 return program;
437} 482}
438 483
439Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { 484Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program,
485 VideoCommon::Shader::AsyncShaders& async_shaders) {
440 if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) { 486 if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) {
441 return last_shaders[static_cast<std::size_t>(program)]; 487 auto* last_shader = last_shaders[static_cast<std::size_t>(program)];
488 if (last_shader->IsBuilt()) {
489 return last_shader;
490 }
442 } 491 }
443 492
444 auto& memory_manager{system.GPU().MemoryManager()}; 493 auto& memory_manager{system.GPU().MemoryManager()};
445 const GPUVAddr address{GetShaderAddress(system, program)}; 494 const GPUVAddr address{GetShaderAddress(system, program)};
446 495
496 if (device.UseAsynchronousShaders() && async_shaders.HasCompletedWork()) {
497 auto completed_work = async_shaders.GetCompletedWork();
498 for (auto& work : completed_work) {
499 Shader* shader = TryGet(work.cpu_address);
500 auto& gpu = system.GPU();
501 gpu.ShaderNotify().MarkShaderComplete();
502 if (shader == nullptr) {
503 continue;
504 }
505 using namespace VideoCommon::Shader;
506 if (work.backend == AsyncShaders::Backend::OpenGL) {
507 shader->AsyncOpenGLBuilt(std::move(work.program.opengl));
508 } else if (work.backend == AsyncShaders::Backend::GLASM) {
509 shader->AsyncGLASMBuilt(std::move(work.program.glasm));
510 }
511
512 ShaderDiskCacheEntry entry;
513 entry.type = work.shader_type;
514 entry.code = std::move(work.code);
515 entry.code_b = std::move(work.code_b);
516 entry.unique_identifier = work.uid;
517
518 auto& registry = shader->GetRegistry();
519
520 entry.bound_buffer = registry.GetBoundBuffer();
521 entry.graphics_info = registry.GetGraphicsInfo();
522 entry.keys = registry.GetKeys();
523 entry.bound_samplers = registry.GetBoundSamplers();
524 entry.bindless_samplers = registry.GetBindlessSamplers();
525 disk_cache.SaveEntry(std::move(entry));
526 }
527 }
528
447 // Look up shader in the cache based on address 529 // Look up shader in the cache based on address
448 const auto cpu_addr{memory_manager.GpuToCpuAddress(address)}; 530 const auto cpu_addr{memory_manager.GpuToCpuAddress(address)};
449 if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) { 531 if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) {
@@ -471,7 +553,8 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
471 std::unique_ptr<Shader> shader; 553 std::unique_ptr<Shader> shader;
472 const auto found = runtime_cache.find(unique_identifier); 554 const auto found = runtime_cache.find(unique_identifier);
473 if (found == runtime_cache.end()) { 555 if (found == runtime_cache.end()) {
474 shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b)); 556 shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b),
557 async_shaders, cpu_addr.value_or(0));
475 } else { 558 } else {
476 shader = Shader::CreateFromCache(params, found->second); 559 shader = Shader::CreateFromCache(params, found->second);
477 } 560 }
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 994aaeaf2..7528ac686 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -33,6 +33,10 @@ namespace Core::Frontend {
33class EmuWindow; 33class EmuWindow;
34} 34}
35 35
36namespace VideoCommon::Shader {
37class AsyncShaders;
38}
39
36namespace OpenGL { 40namespace OpenGL {
37 41
38class Device; 42class Device;
@@ -61,6 +65,11 @@ struct ShaderParameters {
61 u64 unique_identifier; 65 u64 unique_identifier;
62}; 66};
63 67
68ProgramSharedPtr BuildShader(const Device& device, Tegra::Engines::ShaderType shader_type,
69 u64 unique_identifier, const VideoCommon::Shader::ShaderIR& ir,
70 const VideoCommon::Shader::Registry& registry,
71 bool hint_retrievable = false);
72
64class Shader final { 73class Shader final {
65public: 74public:
66 ~Shader(); 75 ~Shader();
@@ -68,15 +77,28 @@ public:
68 /// Gets the GL program handle for the shader 77 /// Gets the GL program handle for the shader
69 GLuint GetHandle() const; 78 GLuint GetHandle() const;
70 79
80 bool IsBuilt() const;
81
71 /// Gets the shader entries for the shader 82 /// Gets the shader entries for the shader
72 const ShaderEntries& GetEntries() const { 83 const ShaderEntries& GetEntries() const {
73 return entries; 84 return entries;
74 } 85 }
75 86
76 static std::unique_ptr<Shader> CreateStageFromMemory(const ShaderParameters& params, 87 const VideoCommon::Shader::Registry& GetRegistry() const {
77 Maxwell::ShaderProgram program_type, 88 return *registry;
78 ProgramCode program_code, 89 }
79 ProgramCode program_code_b); 90
91 /// Mark a OpenGL shader as built
92 void AsyncOpenGLBuilt(OGLProgram new_program);
93
94 /// Mark a GLASM shader as built
95 void AsyncGLASMBuilt(OGLAssemblyProgram new_program);
96
97 static std::unique_ptr<Shader> CreateStageFromMemory(
98 const ShaderParameters& params, Maxwell::ShaderProgram program_type,
99 ProgramCode program_code, ProgramCode program_code_b,
100 VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr);
101
80 static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params, 102 static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params,
81 ProgramCode code); 103 ProgramCode code);
82 104
@@ -85,12 +107,13 @@ public:
85 107
86private: 108private:
87 explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries, 109 explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries,
88 ProgramSharedPtr program); 110 ProgramSharedPtr program, bool is_built = true);
89 111
90 std::shared_ptr<VideoCommon::Shader::Registry> registry; 112 std::shared_ptr<VideoCommon::Shader::Registry> registry;
91 ShaderEntries entries; 113 ShaderEntries entries;
92 ProgramSharedPtr program; 114 ProgramSharedPtr program;
93 GLuint handle = 0; 115 GLuint handle = 0;
116 bool is_built{};
94}; 117};
95 118
96class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> { 119class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> {
@@ -104,7 +127,8 @@ public:
104 const VideoCore::DiskResourceLoadCallback& callback); 127 const VideoCore::DiskResourceLoadCallback& callback);
105 128
106 /// Gets the current specified shader stage program 129 /// Gets the current specified shader stage program
107 Shader* GetStageProgram(Maxwell::ShaderProgram program); 130 Shader* GetStageProgram(Maxwell::ShaderProgram program,
131 VideoCommon::Shader::AsyncShaders& async_shaders);
108 132
109 /// Gets a compute kernel in the passed address 133 /// Gets a compute kernel in the passed address
110 Shader* GetComputeKernel(GPUVAddr code_addr); 134 Shader* GetComputeKernel(GPUVAddr code_addr);
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index fbd406f2b..866813465 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -141,24 +141,28 @@ struct ScreenRectVertex {
141 std::array<f32, 2> tex_coord; 141 std::array<f32, 2> tex_coord;
142 142
143 static VkVertexInputBindingDescription GetDescription() { 143 static VkVertexInputBindingDescription GetDescription() {
144 VkVertexInputBindingDescription description; 144 return {
145 description.binding = 0; 145 .binding = 0,
146 description.stride = sizeof(ScreenRectVertex); 146 .stride = sizeof(ScreenRectVertex),
147 description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 147 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
148 return description; 148 };
149 } 149 }
150 150
151 static std::array<VkVertexInputAttributeDescription, 2> GetAttributes() { 151 static std::array<VkVertexInputAttributeDescription, 2> GetAttributes() {
152 std::array<VkVertexInputAttributeDescription, 2> attributes; 152 return {{
153 attributes[0].location = 0; 153 {
154 attributes[0].binding = 0; 154 .location = 0,
155 attributes[0].format = VK_FORMAT_R32G32_SFLOAT; 155 .binding = 0,
156 attributes[0].offset = offsetof(ScreenRectVertex, position); 156 .format = VK_FORMAT_R32G32_SFLOAT,
157 attributes[1].location = 1; 157 .offset = offsetof(ScreenRectVertex, position),
158 attributes[1].binding = 0; 158 },
159 attributes[1].format = VK_FORMAT_R32G32_SFLOAT; 159 {
160 attributes[1].offset = offsetof(ScreenRectVertex, tex_coord); 160 .location = 1,
161 return attributes; 161 .binding = 0,
162 .format = VK_FORMAT_R32G32_SFLOAT,
163 .offset = offsetof(ScreenRectVertex, tex_coord),
164 },
165 }};
162 } 166 }
163}; 167};
164 168
@@ -267,20 +271,25 @@ std::tuple<VKFence&, VkSemaphore> VKBlitScreen::Draw(const Tegra::FramebufferCon
267 blit_image->Transition(0, 1, 0, 1, VK_PIPELINE_STAGE_TRANSFER_BIT, 271 blit_image->Transition(0, 1, 0, 1, VK_PIPELINE_STAGE_TRANSFER_BIT,
268 VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 272 VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
269 273
270 VkBufferImageCopy copy; 274 const VkBufferImageCopy copy{
271 copy.bufferOffset = image_offset; 275 .bufferOffset = image_offset,
272 copy.bufferRowLength = 0; 276 .bufferRowLength = 0,
273 copy.bufferImageHeight = 0; 277 .bufferImageHeight = 0,
274 copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 278 .imageSubresource =
275 copy.imageSubresource.mipLevel = 0; 279 {
276 copy.imageSubresource.baseArrayLayer = 0; 280 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
277 copy.imageSubresource.layerCount = 1; 281 .mipLevel = 0,
278 copy.imageOffset.x = 0; 282 .baseArrayLayer = 0,
279 copy.imageOffset.y = 0; 283 .layerCount = 1,
280 copy.imageOffset.z = 0; 284 },
281 copy.imageExtent.width = framebuffer.width; 285 .imageOffset = {.x = 0, .y = 0, .z = 0},
282 copy.imageExtent.height = framebuffer.height; 286 .imageExtent =
283 copy.imageExtent.depth = 1; 287 {
288 .width = framebuffer.width,
289 .height = framebuffer.height,
290 .depth = 1,
291 },
292 };
284 scheduler.Record( 293 scheduler.Record(
285 [buffer = *buffer, image = *blit_image->GetHandle(), copy](vk::CommandBuffer cmdbuf) { 294 [buffer = *buffer, image = *blit_image->GetHandle(), copy](vk::CommandBuffer cmdbuf) {
286 cmdbuf.CopyBufferToImage(buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy); 295 cmdbuf.CopyBufferToImage(buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy);
@@ -295,11 +304,9 @@ std::tuple<VKFence&, VkSemaphore> VKBlitScreen::Draw(const Tegra::FramebufferCon
295 descriptor_set = descriptor_sets[image_index], buffer = *buffer, 304 descriptor_set = descriptor_sets[image_index], buffer = *buffer,
296 size = swapchain.GetSize(), pipeline = *pipeline, 305 size = swapchain.GetSize(), pipeline = *pipeline,
297 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { 306 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) {
298 VkClearValue clear_color; 307 const VkClearValue clear_color{
299 clear_color.color.float32[0] = 0.0f; 308 .color = {.float32 = {0.0f, 0.0f, 0.0f, 0.0f}},
300 clear_color.color.float32[1] = 0.0f; 309 };
301 clear_color.color.float32[2] = 0.0f;
302 clear_color.color.float32[3] = 0.0f;
303 310
304 VkRenderPassBeginInfo renderpass_bi; 311 VkRenderPassBeginInfo renderpass_bi;
305 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 312 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -379,93 +386,109 @@ void VKBlitScreen::CreateSemaphores() {
379} 386}
380 387
381void VKBlitScreen::CreateDescriptorPool() { 388void VKBlitScreen::CreateDescriptorPool() {
382 std::array<VkDescriptorPoolSize, 2> pool_sizes; 389 const std::array<VkDescriptorPoolSize, 2> pool_sizes{{
383 pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 390 {
384 pool_sizes[0].descriptorCount = static_cast<u32>(image_count); 391 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
385 pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 392 .descriptorCount = static_cast<u32>(image_count),
386 pool_sizes[1].descriptorCount = static_cast<u32>(image_count); 393 },
387 394 {
388 VkDescriptorPoolCreateInfo ci; 395 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
389 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 396 .descriptorCount = static_cast<u32>(image_count),
390 ci.pNext = nullptr; 397 },
391 ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; 398 }};
392 ci.maxSets = static_cast<u32>(image_count); 399
393 ci.poolSizeCount = static_cast<u32>(pool_sizes.size()); 400 const VkDescriptorPoolCreateInfo ci{
394 ci.pPoolSizes = pool_sizes.data(); 401 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
402 .pNext = nullptr,
403 .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
404 .maxSets = static_cast<u32>(image_count),
405 .poolSizeCount = static_cast<u32>(pool_sizes.size()),
406 .pPoolSizes = pool_sizes.data(),
407 };
395 descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); 408 descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
396} 409}
397 410
398void VKBlitScreen::CreateRenderPass() { 411void VKBlitScreen::CreateRenderPass() {
399 VkAttachmentDescription color_attachment; 412 const VkAttachmentDescription color_attachment{
400 color_attachment.flags = 0; 413 .flags = 0,
401 color_attachment.format = swapchain.GetImageFormat(); 414 .format = swapchain.GetImageFormat(),
402 color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; 415 .samples = VK_SAMPLE_COUNT_1_BIT,
403 color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 416 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
404 color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 417 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
405 color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 418 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
406 color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 419 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
407 color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 420 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
408 color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 421 .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
409 422 };
410 VkAttachmentReference color_attachment_ref; 423
411 color_attachment_ref.attachment = 0; 424 const VkAttachmentReference color_attachment_ref{
412 color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 425 .attachment = 0,
413 426 .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
414 VkSubpassDescription subpass_description; 427 };
415 subpass_description.flags = 0; 428
416 subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 429 const VkSubpassDescription subpass_description{
417 subpass_description.inputAttachmentCount = 0; 430 .flags = 0,
418 subpass_description.pInputAttachments = nullptr; 431 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
419 subpass_description.colorAttachmentCount = 1; 432 .inputAttachmentCount = 0,
420 subpass_description.pColorAttachments = &color_attachment_ref; 433 .pInputAttachments = nullptr,
421 subpass_description.pResolveAttachments = nullptr; 434 .colorAttachmentCount = 1,
422 subpass_description.pDepthStencilAttachment = nullptr; 435 .pColorAttachments = &color_attachment_ref,
423 subpass_description.preserveAttachmentCount = 0; 436 .pResolveAttachments = nullptr,
424 subpass_description.pPreserveAttachments = nullptr; 437 .pDepthStencilAttachment = nullptr,
425 438 .preserveAttachmentCount = 0,
426 VkSubpassDependency dependency; 439 .pPreserveAttachments = nullptr,
427 dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 440 };
428 dependency.dstSubpass = 0; 441
429 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 442 const VkSubpassDependency dependency{
430 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 443 .srcSubpass = VK_SUBPASS_EXTERNAL,
431 dependency.srcAccessMask = 0; 444 .dstSubpass = 0,
432 dependency.dstAccessMask = 445 .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
433 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 446 .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
434 dependency.dependencyFlags = 0; 447 .srcAccessMask = 0,
435 448 .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
436 VkRenderPassCreateInfo renderpass_ci; 449 .dependencyFlags = 0,
437 renderpass_ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 450 };
438 renderpass_ci.pNext = nullptr; 451
439 renderpass_ci.flags = 0; 452 const VkRenderPassCreateInfo renderpass_ci{
440 renderpass_ci.attachmentCount = 1; 453 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
441 renderpass_ci.pAttachments = &color_attachment; 454 .pNext = nullptr,
442 renderpass_ci.subpassCount = 1; 455 .flags = 0,
443 renderpass_ci.pSubpasses = &subpass_description; 456 .attachmentCount = 1,
444 renderpass_ci.dependencyCount = 1; 457 .pAttachments = &color_attachment,
445 renderpass_ci.pDependencies = &dependency; 458 .subpassCount = 1,
459 .pSubpasses = &subpass_description,
460 .dependencyCount = 1,
461 .pDependencies = &dependency,
462 };
446 463
447 renderpass = device.GetLogical().CreateRenderPass(renderpass_ci); 464 renderpass = device.GetLogical().CreateRenderPass(renderpass_ci);
448} 465}
449 466
450void VKBlitScreen::CreateDescriptorSetLayout() { 467void VKBlitScreen::CreateDescriptorSetLayout() {
451 std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings; 468 const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{
452 layout_bindings[0].binding = 0; 469 {
453 layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 470 .binding = 0,
454 layout_bindings[0].descriptorCount = 1; 471 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
455 layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 472 .descriptorCount = 1,
456 layout_bindings[0].pImmutableSamplers = nullptr; 473 .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
457 layout_bindings[1].binding = 1; 474 .pImmutableSamplers = nullptr,
458 layout_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 475 },
459 layout_bindings[1].descriptorCount = 1; 476 {
460 layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 477 .binding = 1,
461 layout_bindings[1].pImmutableSamplers = nullptr; 478 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
462 479 .descriptorCount = 1,
463 VkDescriptorSetLayoutCreateInfo ci; 480 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
464 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 481 .pImmutableSamplers = nullptr,
465 ci.pNext = nullptr; 482 },
466 ci.flags = 0; 483 }};
467 ci.bindingCount = static_cast<u32>(layout_bindings.size()); 484
468 ci.pBindings = layout_bindings.data(); 485 const VkDescriptorSetLayoutCreateInfo ci{
486 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
487 .pNext = nullptr,
488 .flags = 0,
489 .bindingCount = static_cast<u32>(layout_bindings.size()),
490 .pBindings = layout_bindings.data(),
491 };
469 492
470 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); 493 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
471} 494}
@@ -473,175 +496,192 @@ void VKBlitScreen::CreateDescriptorSetLayout() {
473void VKBlitScreen::CreateDescriptorSets() { 496void VKBlitScreen::CreateDescriptorSets() {
474 const std::vector layouts(image_count, *descriptor_set_layout); 497 const std::vector layouts(image_count, *descriptor_set_layout);
475 498
476 VkDescriptorSetAllocateInfo ai; 499 const VkDescriptorSetAllocateInfo ai{
477 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 500 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
478 ai.pNext = nullptr; 501 .pNext = nullptr,
479 ai.descriptorPool = *descriptor_pool; 502 .descriptorPool = *descriptor_pool,
480 ai.descriptorSetCount = static_cast<u32>(image_count); 503 .descriptorSetCount = static_cast<u32>(image_count),
481 ai.pSetLayouts = layouts.data(); 504 .pSetLayouts = layouts.data(),
505 };
506
482 descriptor_sets = descriptor_pool.Allocate(ai); 507 descriptor_sets = descriptor_pool.Allocate(ai);
483} 508}
484 509
485void VKBlitScreen::CreatePipelineLayout() { 510void VKBlitScreen::CreatePipelineLayout() {
486 VkPipelineLayoutCreateInfo ci; 511 const VkPipelineLayoutCreateInfo ci{
487 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 512 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
488 ci.pNext = nullptr; 513 .pNext = nullptr,
489 ci.flags = 0; 514 .flags = 0,
490 ci.setLayoutCount = 1; 515 .setLayoutCount = 1,
491 ci.pSetLayouts = descriptor_set_layout.address(); 516 .pSetLayouts = descriptor_set_layout.address(),
492 ci.pushConstantRangeCount = 0; 517 .pushConstantRangeCount = 0,
493 ci.pPushConstantRanges = nullptr; 518 .pPushConstantRanges = nullptr,
519 };
494 pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); 520 pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
495} 521}
496 522
497void VKBlitScreen::CreateGraphicsPipeline() { 523void VKBlitScreen::CreateGraphicsPipeline() {
498 std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages; 524 const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{
499 shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 525 {
500 shader_stages[0].pNext = nullptr; 526 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
501 shader_stages[0].flags = 0; 527 .pNext = nullptr,
502 shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 528 .flags = 0,
503 shader_stages[0].module = *vertex_shader; 529 .stage = VK_SHADER_STAGE_VERTEX_BIT,
504 shader_stages[0].pName = "main"; 530 .module = *vertex_shader,
505 shader_stages[0].pSpecializationInfo = nullptr; 531 .pName = "main",
506 shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 532 .pSpecializationInfo = nullptr,
507 shader_stages[1].pNext = nullptr; 533 },
508 shader_stages[1].flags = 0; 534 {
509 shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 535 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
510 shader_stages[1].module = *fragment_shader; 536 .pNext = nullptr,
511 shader_stages[1].pName = "main"; 537 .flags = 0,
512 shader_stages[1].pSpecializationInfo = nullptr; 538 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
539 .module = *fragment_shader,
540 .pName = "main",
541 .pSpecializationInfo = nullptr,
542 },
543 }};
513 544
514 const auto vertex_binding_description = ScreenRectVertex::GetDescription(); 545 const auto vertex_binding_description = ScreenRectVertex::GetDescription();
515 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes(); 546 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
516 547
517 VkPipelineVertexInputStateCreateInfo vertex_input_ci; 548 const VkPipelineVertexInputStateCreateInfo vertex_input_ci{
518 vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 549 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
519 vertex_input_ci.pNext = nullptr; 550 .pNext = nullptr,
520 vertex_input_ci.flags = 0; 551 .flags = 0,
521 vertex_input_ci.vertexBindingDescriptionCount = 1; 552 .vertexBindingDescriptionCount = 1,
522 vertex_input_ci.pVertexBindingDescriptions = &vertex_binding_description; 553 .pVertexBindingDescriptions = &vertex_binding_description,
523 vertex_input_ci.vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()}; 554 .vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()},
524 vertex_input_ci.pVertexAttributeDescriptions = vertex_attrs_description.data(); 555 .pVertexAttributeDescriptions = vertex_attrs_description.data(),
525 556 };
526 VkPipelineInputAssemblyStateCreateInfo input_assembly_ci; 557
527 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 558 const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
528 input_assembly_ci.pNext = nullptr; 559 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
529 input_assembly_ci.flags = 0; 560 .pNext = nullptr,
530 input_assembly_ci.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 561 .flags = 0,
531 input_assembly_ci.primitiveRestartEnable = VK_FALSE; 562 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
532 563 .primitiveRestartEnable = VK_FALSE,
533 VkPipelineViewportStateCreateInfo viewport_state_ci; 564 };
534 viewport_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 565
535 viewport_state_ci.pNext = nullptr; 566 const VkPipelineViewportStateCreateInfo viewport_state_ci{
536 viewport_state_ci.flags = 0; 567 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
537 viewport_state_ci.viewportCount = 1; 568 .pNext = nullptr,
538 viewport_state_ci.pViewports = nullptr; 569 .flags = 0,
539 viewport_state_ci.scissorCount = 1; 570 .viewportCount = 1,
540 viewport_state_ci.pScissors = nullptr; 571 .pViewports = nullptr,
541 572 .scissorCount = 1,
542 VkPipelineRasterizationStateCreateInfo rasterization_ci; 573 .pScissors = nullptr,
543 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 574 };
544 rasterization_ci.pNext = nullptr; 575
545 rasterization_ci.flags = 0; 576 const VkPipelineRasterizationStateCreateInfo rasterization_ci{
546 rasterization_ci.depthClampEnable = VK_FALSE; 577 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
547 rasterization_ci.rasterizerDiscardEnable = VK_FALSE; 578 .pNext = nullptr,
548 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 579 .flags = 0,
549 rasterization_ci.cullMode = VK_CULL_MODE_NONE; 580 .depthClampEnable = VK_FALSE,
550 rasterization_ci.frontFace = VK_FRONT_FACE_CLOCKWISE; 581 .rasterizerDiscardEnable = VK_FALSE,
551 rasterization_ci.depthBiasEnable = VK_FALSE; 582 .polygonMode = VK_POLYGON_MODE_FILL,
552 rasterization_ci.depthBiasConstantFactor = 0.0f; 583 .cullMode = VK_CULL_MODE_NONE,
553 rasterization_ci.depthBiasClamp = 0.0f; 584 .frontFace = VK_FRONT_FACE_CLOCKWISE,
554 rasterization_ci.depthBiasSlopeFactor = 0.0f; 585 .depthBiasEnable = VK_FALSE,
555 rasterization_ci.lineWidth = 1.0f; 586 .depthBiasConstantFactor = 0.0f,
556 587 .depthBiasClamp = 0.0f,
557 VkPipelineMultisampleStateCreateInfo multisampling_ci; 588 .depthBiasSlopeFactor = 0.0f,
558 multisampling_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 589 .lineWidth = 1.0f,
559 multisampling_ci.pNext = nullptr; 590 };
560 multisampling_ci.flags = 0; 591
561 multisampling_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 592 const VkPipelineMultisampleStateCreateInfo multisampling_ci{
562 multisampling_ci.sampleShadingEnable = VK_FALSE; 593 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
563 multisampling_ci.minSampleShading = 0.0f; 594 .pNext = nullptr,
564 multisampling_ci.pSampleMask = nullptr; 595 .flags = 0,
565 multisampling_ci.alphaToCoverageEnable = VK_FALSE; 596 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
566 multisampling_ci.alphaToOneEnable = VK_FALSE; 597 .sampleShadingEnable = VK_FALSE,
567 598 .minSampleShading = 0.0f,
568 VkPipelineColorBlendAttachmentState color_blend_attachment; 599 .pSampleMask = nullptr,
569 color_blend_attachment.blendEnable = VK_FALSE; 600 .alphaToCoverageEnable = VK_FALSE,
570 color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO; 601 .alphaToOneEnable = VK_FALSE,
571 color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; 602 };
572 color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD; 603
573 color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 604 const VkPipelineColorBlendAttachmentState color_blend_attachment{
574 color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 605 .blendEnable = VK_FALSE,
575 color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD; 606 .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
576 color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 607 .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
577 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 608 .colorBlendOp = VK_BLEND_OP_ADD,
578 609 .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
579 VkPipelineColorBlendStateCreateInfo color_blend_ci; 610 .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
580 color_blend_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 611 .alphaBlendOp = VK_BLEND_OP_ADD,
581 color_blend_ci.flags = 0; 612 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
582 color_blend_ci.pNext = nullptr; 613 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
583 color_blend_ci.logicOpEnable = VK_FALSE; 614 };
584 color_blend_ci.logicOp = VK_LOGIC_OP_COPY; 615
585 color_blend_ci.attachmentCount = 1; 616 const VkPipelineColorBlendStateCreateInfo color_blend_ci{
586 color_blend_ci.pAttachments = &color_blend_attachment; 617 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
587 color_blend_ci.blendConstants[0] = 0.0f; 618 .pNext = nullptr,
588 color_blend_ci.blendConstants[1] = 0.0f; 619 .flags = 0,
589 color_blend_ci.blendConstants[2] = 0.0f; 620 .logicOpEnable = VK_FALSE,
590 color_blend_ci.blendConstants[3] = 0.0f; 621 .logicOp = VK_LOGIC_OP_COPY,
591 622 .attachmentCount = 1,
592 static constexpr std::array dynamic_states = {VK_DYNAMIC_STATE_VIEWPORT, 623 .pAttachments = &color_blend_attachment,
593 VK_DYNAMIC_STATE_SCISSOR}; 624 .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
594 VkPipelineDynamicStateCreateInfo dynamic_state_ci; 625 };
595 dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 626
596 dynamic_state_ci.pNext = nullptr; 627 static constexpr std::array dynamic_states{
597 dynamic_state_ci.flags = 0; 628 VK_DYNAMIC_STATE_VIEWPORT,
598 dynamic_state_ci.dynamicStateCount = static_cast<u32>(dynamic_states.size()); 629 VK_DYNAMIC_STATE_SCISSOR,
599 dynamic_state_ci.pDynamicStates = dynamic_states.data(); 630 };
600 631 const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
601 VkGraphicsPipelineCreateInfo pipeline_ci; 632 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
602 pipeline_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 633 .pNext = nullptr,
603 pipeline_ci.pNext = nullptr; 634 .flags = 0,
604 pipeline_ci.flags = 0; 635 .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
605 pipeline_ci.stageCount = static_cast<u32>(shader_stages.size()); 636 .pDynamicStates = dynamic_states.data(),
606 pipeline_ci.pStages = shader_stages.data(); 637 };
607 pipeline_ci.pVertexInputState = &vertex_input_ci; 638
608 pipeline_ci.pInputAssemblyState = &input_assembly_ci; 639 const VkGraphicsPipelineCreateInfo pipeline_ci{
609 pipeline_ci.pTessellationState = nullptr; 640 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
610 pipeline_ci.pViewportState = &viewport_state_ci; 641 .pNext = nullptr,
611 pipeline_ci.pRasterizationState = &rasterization_ci; 642 .flags = 0,
612 pipeline_ci.pMultisampleState = &multisampling_ci; 643 .stageCount = static_cast<u32>(shader_stages.size()),
613 pipeline_ci.pDepthStencilState = nullptr; 644 .pStages = shader_stages.data(),
614 pipeline_ci.pColorBlendState = &color_blend_ci; 645 .pVertexInputState = &vertex_input_ci,
615 pipeline_ci.pDynamicState = &dynamic_state_ci; 646 .pInputAssemblyState = &input_assembly_ci,
616 pipeline_ci.layout = *pipeline_layout; 647 .pTessellationState = nullptr,
617 pipeline_ci.renderPass = *renderpass; 648 .pViewportState = &viewport_state_ci,
618 pipeline_ci.subpass = 0; 649 .pRasterizationState = &rasterization_ci,
619 pipeline_ci.basePipelineHandle = 0; 650 .pMultisampleState = &multisampling_ci,
620 pipeline_ci.basePipelineIndex = 0; 651 .pDepthStencilState = nullptr,
652 .pColorBlendState = &color_blend_ci,
653 .pDynamicState = &dynamic_state_ci,
654 .layout = *pipeline_layout,
655 .renderPass = *renderpass,
656 .subpass = 0,
657 .basePipelineHandle = 0,
658 .basePipelineIndex = 0,
659 };
621 660
622 pipeline = device.GetLogical().CreateGraphicsPipeline(pipeline_ci); 661 pipeline = device.GetLogical().CreateGraphicsPipeline(pipeline_ci);
623} 662}
624 663
625void VKBlitScreen::CreateSampler() { 664void VKBlitScreen::CreateSampler() {
626 VkSamplerCreateInfo ci; 665 const VkSamplerCreateInfo ci{
627 ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 666 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
628 ci.pNext = nullptr; 667 .pNext = nullptr,
629 ci.flags = 0; 668 .flags = 0,
630 ci.magFilter = VK_FILTER_LINEAR; 669 .magFilter = VK_FILTER_LINEAR,
631 ci.minFilter = VK_FILTER_NEAREST; 670 .minFilter = VK_FILTER_NEAREST,
632 ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 671 .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
633 ci.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 672 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
634 ci.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 673 .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
635 ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 674 .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
636 ci.mipLodBias = 0.0f; 675 .mipLodBias = 0.0f,
637 ci.anisotropyEnable = VK_FALSE; 676 .anisotropyEnable = VK_FALSE,
638 ci.maxAnisotropy = 0.0f; 677 .maxAnisotropy = 0.0f,
639 ci.compareEnable = VK_FALSE; 678 .compareEnable = VK_FALSE,
640 ci.compareOp = VK_COMPARE_OP_NEVER; 679 .compareOp = VK_COMPARE_OP_NEVER,
641 ci.minLod = 0.0f; 680 .minLod = 0.0f,
642 ci.maxLod = 0.0f; 681 .maxLod = 0.0f,
643 ci.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; 682 .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
644 ci.unnormalizedCoordinates = VK_FALSE; 683 .unnormalizedCoordinates = VK_FALSE,
684 };
645 685
646 sampler = device.GetLogical().CreateSampler(ci); 686 sampler = device.GetLogical().CreateSampler(ci);
647} 687}
@@ -650,15 +690,16 @@ void VKBlitScreen::CreateFramebuffers() {
650 const VkExtent2D size{swapchain.GetSize()}; 690 const VkExtent2D size{swapchain.GetSize()};
651 framebuffers.resize(image_count); 691 framebuffers.resize(image_count);
652 692
653 VkFramebufferCreateInfo ci; 693 VkFramebufferCreateInfo ci{
654 ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 694 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
655 ci.pNext = nullptr; 695 .pNext = nullptr,
656 ci.flags = 0; 696 .flags = 0,
657 ci.renderPass = *renderpass; 697 .renderPass = *renderpass,
658 ci.attachmentCount = 1; 698 .attachmentCount = 1,
659 ci.width = size.width; 699 .width = size.width,
660 ci.height = size.height; 700 .height = size.height,
661 ci.layers = 1; 701 .layers = 1,
702 };
662 703
663 for (std::size_t i = 0; i < image_count; ++i) { 704 for (std::size_t i = 0; i < image_count; ++i) {
664 const VkImageView image_view{swapchain.GetImageViewIndex(i)}; 705 const VkImageView image_view{swapchain.GetImageViewIndex(i)};
@@ -678,16 +719,17 @@ void VKBlitScreen::ReleaseRawImages() {
678} 719}
679 720
680void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { 721void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
681 VkBufferCreateInfo ci; 722 const VkBufferCreateInfo ci{
682 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 723 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
683 ci.pNext = nullptr; 724 .pNext = nullptr,
684 ci.flags = 0; 725 .flags = 0,
685 ci.size = CalculateBufferSize(framebuffer); 726 .size = CalculateBufferSize(framebuffer),
686 ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | 727 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
687 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 728 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
688 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 729 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
689 ci.queueFamilyIndexCount = 0; 730 .queueFamilyIndexCount = 0,
690 ci.pQueueFamilyIndices = nullptr; 731 .pQueueFamilyIndices = nullptr,
732 };
691 733
692 buffer = device.GetLogical().CreateBuffer(ci); 734 buffer = device.GetLogical().CreateBuffer(ci);
693 buffer_commit = memory_manager.Commit(buffer, true); 735 buffer_commit = memory_manager.Commit(buffer, true);
@@ -697,24 +739,28 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
697 raw_images.resize(image_count); 739 raw_images.resize(image_count);
698 raw_buffer_commits.resize(image_count); 740 raw_buffer_commits.resize(image_count);
699 741
700 VkImageCreateInfo ci; 742 const VkImageCreateInfo ci{
701 ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 743 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
702 ci.pNext = nullptr; 744 .pNext = nullptr,
703 ci.flags = 0; 745 .flags = 0,
704 ci.imageType = VK_IMAGE_TYPE_2D; 746 .imageType = VK_IMAGE_TYPE_2D,
705 ci.format = GetFormat(framebuffer); 747 .format = GetFormat(framebuffer),
706 ci.extent.width = framebuffer.width; 748 .extent =
707 ci.extent.height = framebuffer.height; 749 {
708 ci.extent.depth = 1; 750 .width = framebuffer.width,
709 ci.mipLevels = 1; 751 .height = framebuffer.height,
710 ci.arrayLayers = 1; 752 .depth = 1,
711 ci.samples = VK_SAMPLE_COUNT_1_BIT; 753 },
712 ci.tiling = VK_IMAGE_TILING_LINEAR; 754 .mipLevels = 1,
713 ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 755 .arrayLayers = 1,
714 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 756 .samples = VK_SAMPLE_COUNT_1_BIT,
715 ci.queueFamilyIndexCount = 0; 757 .tiling = VK_IMAGE_TILING_LINEAR,
716 ci.pQueueFamilyIndices = nullptr; 758 .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
717 ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 759 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
760 .queueFamilyIndexCount = 0,
761 .pQueueFamilyIndices = nullptr,
762 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
763 };
718 764
719 for (std::size_t i = 0; i < image_count; ++i) { 765 for (std::size_t i = 0; i < image_count; ++i) {
720 raw_images[i] = std::make_unique<VKImage>(device, scheduler, ci, VK_IMAGE_ASPECT_COLOR_BIT); 766 raw_images[i] = std::make_unique<VKImage>(device, scheduler, ci, VK_IMAGE_ASPECT_COLOR_BIT);
@@ -723,39 +769,43 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
723} 769}
724 770
725void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const { 771void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const {
726 VkDescriptorBufferInfo buffer_info; 772 const VkDescriptorBufferInfo buffer_info{
727 buffer_info.buffer = *buffer; 773 .buffer = *buffer,
728 buffer_info.offset = offsetof(BufferData, uniform); 774 .offset = offsetof(BufferData, uniform),
729 buffer_info.range = sizeof(BufferData::uniform); 775 .range = sizeof(BufferData::uniform),
730 776 };
731 VkWriteDescriptorSet ubo_write; 777
732 ubo_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 778 const VkWriteDescriptorSet ubo_write{
733 ubo_write.pNext = nullptr; 779 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
734 ubo_write.dstSet = descriptor_sets[image_index]; 780 .pNext = nullptr,
735 ubo_write.dstBinding = 0; 781 .dstSet = descriptor_sets[image_index],
736 ubo_write.dstArrayElement = 0; 782 .dstBinding = 0,
737 ubo_write.descriptorCount = 1; 783 .dstArrayElement = 0,
738 ubo_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 784 .descriptorCount = 1,
739 ubo_write.pImageInfo = nullptr; 785 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
740 ubo_write.pBufferInfo = &buffer_info; 786 .pImageInfo = nullptr,
741 ubo_write.pTexelBufferView = nullptr; 787 .pBufferInfo = &buffer_info,
742 788 .pTexelBufferView = nullptr,
743 VkDescriptorImageInfo image_info; 789 };
744 image_info.sampler = *sampler; 790
745 image_info.imageView = image_view; 791 const VkDescriptorImageInfo image_info{
746 image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 792 .sampler = *sampler,
747 793 .imageView = image_view,
748 VkWriteDescriptorSet sampler_write; 794 .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
749 sampler_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 795 };
750 sampler_write.pNext = nullptr; 796
751 sampler_write.dstSet = descriptor_sets[image_index]; 797 const VkWriteDescriptorSet sampler_write{
752 sampler_write.dstBinding = 1; 798 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
753 sampler_write.dstArrayElement = 0; 799 .pNext = nullptr,
754 sampler_write.descriptorCount = 1; 800 .dstSet = descriptor_sets[image_index],
755 sampler_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 801 .dstBinding = 1,
756 sampler_write.pImageInfo = &image_info; 802 .dstArrayElement = 0,
757 sampler_write.pBufferInfo = nullptr; 803 .descriptorCount = 1,
758 sampler_write.pTexelBufferView = nullptr; 804 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
805 .pImageInfo = &image_info,
806 .pBufferInfo = nullptr,
807 .pTexelBufferView = nullptr,
808 };
759 809
760 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {}); 810 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {});
761} 811}
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 2be38d419..1d2f8b557 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -39,16 +39,17 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch
39 39
40Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, 40Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_,
41 VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) 41 VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size)
42 : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { 42 : BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} {
43 VkBufferCreateInfo ci; 43 const VkBufferCreateInfo ci{
44 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 44 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
45 ci.pNext = nullptr; 45 .pNext = nullptr,
46 ci.flags = 0; 46 .flags = 0,
47 ci.size = static_cast<VkDeviceSize>(size); 47 .size = static_cast<VkDeviceSize>(size),
48 ci.usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 48 .usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
49 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 49 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
50 ci.queueFamilyIndexCount = 0; 50 .queueFamilyIndexCount = 0,
51 ci.pQueueFamilyIndices = nullptr; 51 .pQueueFamilyIndices = nullptr,
52 };
52 53
53 buffer.handle = device.GetLogical().CreateBuffer(ci); 54 buffer.handle = device.GetLogical().CreateBuffer(ci);
54 buffer.commit = memory_manager.Commit(buffer.handle, false); 55 buffer.commit = memory_manager.Commit(buffer.handle, false);
@@ -66,16 +67,17 @@ void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) {
66 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { 67 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
67 cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); 68 cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size});
68 69
69 VkBufferMemoryBarrier barrier; 70 const VkBufferMemoryBarrier barrier{
70 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 71 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
71 barrier.pNext = nullptr; 72 .pNext = nullptr,
72 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 73 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
73 barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; 74 .dstAccessMask = UPLOAD_ACCESS_BARRIERS,
74 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 75 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
75 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 76 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
76 barrier.buffer = handle; 77 .buffer = handle,
77 barrier.offset = offset; 78 .offset = offset,
78 barrier.size = size; 79 .size = size,
80 };
79 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, 81 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {},
80 barrier, {}); 82 barrier, {});
81 }); 83 });
@@ -87,16 +89,17 @@ void Buffer::Download(std::size_t offset, std::size_t size, u8* data) {
87 89
88 const VkBuffer handle = Handle(); 90 const VkBuffer handle = Handle();
89 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { 91 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
90 VkBufferMemoryBarrier barrier; 92 const VkBufferMemoryBarrier barrier{
91 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 93 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
92 barrier.pNext = nullptr; 94 .pNext = nullptr,
93 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 95 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
94 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 96 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
95 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 97 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
96 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 98 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
97 barrier.buffer = handle; 99 .buffer = handle,
98 barrier.offset = offset; 100 .offset = offset,
99 barrier.size = size; 101 .size = size,
102 };
100 103
101 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | 104 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
102 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | 105 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index da71e710c..182461ed9 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -115,32 +115,32 @@ constexpr u8 quad_array[] = {
115 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; 115 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
116 116
117VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() { 117VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() {
118 VkDescriptorSetLayoutBinding binding; 118 return {
119 binding.binding = 0; 119 .binding = 0,
120 binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 120 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
121 binding.descriptorCount = 1; 121 .descriptorCount = 1,
122 binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 122 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
123 binding.pImmutableSamplers = nullptr; 123 .pImmutableSamplers = nullptr,
124 return binding; 124 };
125} 125}
126 126
127VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() { 127VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() {
128 VkDescriptorUpdateTemplateEntryKHR entry; 128 return {
129 entry.dstBinding = 0; 129 .dstBinding = 0,
130 entry.dstArrayElement = 0; 130 .dstArrayElement = 0,
131 entry.descriptorCount = 1; 131 .descriptorCount = 1,
132 entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 132 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
133 entry.offset = 0; 133 .offset = 0,
134 entry.stride = sizeof(DescriptorUpdateEntry); 134 .stride = sizeof(DescriptorUpdateEntry),
135 return entry; 135 };
136} 136}
137 137
138VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { 138VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
139 VkPushConstantRange range; 139 return {
140 range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 140 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
141 range.offset = 0; 141 .offset = 0,
142 range.size = static_cast<u32>(size); 142 .size = static_cast<u32>(size),
143 return range; 143 };
144} 144}
145 145
146// Uint8 SPIR-V module. Generated from the "shaders/" directory. 146// Uint8 SPIR-V module. Generated from the "shaders/" directory.
@@ -344,29 +344,33 @@ constexpr u8 QUAD_INDEXED_SPV[] = {
344 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; 344 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
345 345
346std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() { 346std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() {
347 std::array<VkDescriptorSetLayoutBinding, 2> bindings; 347 return {{
348 bindings[0].binding = 0; 348 {
349 bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 349 .binding = 0,
350 bindings[0].descriptorCount = 1; 350 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
351 bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 351 .descriptorCount = 1,
352 bindings[0].pImmutableSamplers = nullptr; 352 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
353 bindings[1].binding = 1; 353 .pImmutableSamplers = nullptr,
354 bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 354 },
355 bindings[1].descriptorCount = 1; 355 {
356 bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 356 .binding = 1,
357 bindings[1].pImmutableSamplers = nullptr; 357 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
358 return bindings; 358 .descriptorCount = 1,
359 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
360 .pImmutableSamplers = nullptr,
361 },
362 }};
359} 363}
360 364
361VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { 365VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
362 VkDescriptorUpdateTemplateEntryKHR entry; 366 return {
363 entry.dstBinding = 0; 367 .dstBinding = 0,
364 entry.dstArrayElement = 0; 368 .dstArrayElement = 0,
365 entry.descriptorCount = 2; 369 .descriptorCount = 2,
366 entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 370 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
367 entry.offset = 0; 371 .offset = 0,
368 entry.stride = sizeof(DescriptorUpdateEntry); 372 .stride = sizeof(DescriptorUpdateEntry),
369 return entry; 373 };
370} 374}
371 375
372} // Anonymous namespace 376} // Anonymous namespace
@@ -376,37 +380,37 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
376 vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, 380 vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
377 vk::Span<VkPushConstantRange> push_constants, std::size_t code_size, 381 vk::Span<VkPushConstantRange> push_constants, std::size_t code_size,
378 const u8* code) { 382 const u8* code) {
379 VkDescriptorSetLayoutCreateInfo descriptor_layout_ci; 383 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({
380 descriptor_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 384 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
381 descriptor_layout_ci.pNext = nullptr; 385 .pNext = nullptr,
382 descriptor_layout_ci.flags = 0; 386 .flags = 0,
383 descriptor_layout_ci.bindingCount = bindings.size(); 387 .bindingCount = bindings.size(),
384 descriptor_layout_ci.pBindings = bindings.data(); 388 .pBindings = bindings.data(),
385 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(descriptor_layout_ci); 389 });
386 390
387 VkPipelineLayoutCreateInfo pipeline_layout_ci; 391 layout = device.GetLogical().CreatePipelineLayout({
388 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 392 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
389 pipeline_layout_ci.pNext = nullptr; 393 .pNext = nullptr,
390 pipeline_layout_ci.flags = 0; 394 .flags = 0,
391 pipeline_layout_ci.setLayoutCount = 1; 395 .setLayoutCount = 1,
392 pipeline_layout_ci.pSetLayouts = descriptor_set_layout.address(); 396 .pSetLayouts = descriptor_set_layout.address(),
393 pipeline_layout_ci.pushConstantRangeCount = push_constants.size(); 397 .pushConstantRangeCount = push_constants.size(),
394 pipeline_layout_ci.pPushConstantRanges = push_constants.data(); 398 .pPushConstantRanges = push_constants.data(),
395 layout = device.GetLogical().CreatePipelineLayout(pipeline_layout_ci); 399 });
396 400
397 if (!templates.empty()) { 401 if (!templates.empty()) {
398 VkDescriptorUpdateTemplateCreateInfoKHR template_ci; 402 descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR({
399 template_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 403 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
400 template_ci.pNext = nullptr; 404 .pNext = nullptr,
401 template_ci.flags = 0; 405 .flags = 0,
402 template_ci.descriptorUpdateEntryCount = templates.size(); 406 .descriptorUpdateEntryCount = templates.size(),
403 template_ci.pDescriptorUpdateEntries = templates.data(); 407 .pDescriptorUpdateEntries = templates.data(),
404 template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 408 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
405 template_ci.descriptorSetLayout = *descriptor_set_layout; 409 .descriptorSetLayout = *descriptor_set_layout,
406 template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 410 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
407 template_ci.pipelineLayout = *layout; 411 .pipelineLayout = *layout,
408 template_ci.set = 0; 412 .set = 0,
409 descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR(template_ci); 413 });
410 414
411 descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout); 415 descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout);
412 } 416 }
@@ -414,32 +418,32 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
414 auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1); 418 auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1);
415 std::memcpy(code_copy.get(), code, code_size); 419 std::memcpy(code_copy.get(), code, code_size);
416 420
417 VkShaderModuleCreateInfo module_ci; 421 module = device.GetLogical().CreateShaderModule({
418 module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 422 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
419 module_ci.pNext = nullptr; 423 .pNext = nullptr,
420 module_ci.flags = 0; 424 .flags = 0,
421 module_ci.codeSize = code_size; 425 .codeSize = code_size,
422 module_ci.pCode = code_copy.get(); 426 .pCode = code_copy.get(),
423 module = device.GetLogical().CreateShaderModule(module_ci); 427 });
424 428
425 VkComputePipelineCreateInfo pipeline_ci; 429 pipeline = device.GetLogical().CreateComputePipeline({
426 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 430 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
427 pipeline_ci.pNext = nullptr; 431 .pNext = nullptr,
428 pipeline_ci.flags = 0; 432 .flags = 0,
429 pipeline_ci.layout = *layout; 433 .stage =
430 pipeline_ci.basePipelineHandle = nullptr; 434 {
431 pipeline_ci.basePipelineIndex = 0; 435 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
432 436 .pNext = nullptr,
433 VkPipelineShaderStageCreateInfo& stage_ci = pipeline_ci.stage; 437 .flags = 0,
434 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 438 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
435 stage_ci.pNext = nullptr; 439 .module = *module,
436 stage_ci.flags = 0; 440 .pName = "main",
437 stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; 441 .pSpecializationInfo = nullptr,
438 stage_ci.module = *module; 442 },
439 stage_ci.pName = "main"; 443 .layout = *layout,
440 stage_ci.pSpecializationInfo = nullptr; 444 .basePipelineHandle = nullptr,
441 445 .basePipelineIndex = 0,
442 pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci); 446 });
443} 447}
444 448
445VKComputePass::~VKComputePass() = default; 449VKComputePass::~VKComputePass() = default;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 281bf9ac3..ed9d2991c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -43,12 +43,13 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
43 const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) { 43 const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) {
44 // TODO(Rodrigo): Maybe make individual bindings here? 44 // TODO(Rodrigo): Maybe make individual bindings here?
45 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) { 45 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) {
46 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); 46 bindings.push_back({
47 entry.binding = binding++; 47 .binding = binding++,
48 entry.descriptorType = descriptor_type; 48 .descriptorType = descriptor_type,
49 entry.descriptorCount = 1; 49 .descriptorCount = 1,
50 entry.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 50 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
51 entry.pImmutableSamplers = nullptr; 51 .pImmutableSamplers = nullptr,
52 });
52 } 53 }
53 }; 54 };
54 add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); 55 add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size());
@@ -58,25 +59,25 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
58 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size()); 59 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size());
59 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); 60 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size());
60 61
61 VkDescriptorSetLayoutCreateInfo ci; 62 return device.GetLogical().CreateDescriptorSetLayout({
62 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 63 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
63 ci.pNext = nullptr; 64 .pNext = nullptr,
64 ci.flags = 0; 65 .flags = 0,
65 ci.bindingCount = static_cast<u32>(bindings.size()); 66 .bindingCount = static_cast<u32>(bindings.size()),
66 ci.pBindings = bindings.data(); 67 .pBindings = bindings.data(),
67 return device.GetLogical().CreateDescriptorSetLayout(ci); 68 });
68} 69}
69 70
70vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const { 71vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const {
71 VkPipelineLayoutCreateInfo ci; 72 return device.GetLogical().CreatePipelineLayout({
72 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 73 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
73 ci.pNext = nullptr; 74 .pNext = nullptr,
74 ci.flags = 0; 75 .flags = 0,
75 ci.setLayoutCount = 1; 76 .setLayoutCount = 1,
76 ci.pSetLayouts = descriptor_set_layout.address(); 77 .pSetLayouts = descriptor_set_layout.address(),
77 ci.pushConstantRangeCount = 0; 78 .pushConstantRangeCount = 0,
78 ci.pPushConstantRanges = nullptr; 79 .pPushConstantRanges = nullptr,
79 return device.GetLogical().CreatePipelineLayout(ci); 80 });
80} 81}
81 82
82vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const { 83vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const {
@@ -89,59 +90,63 @@ vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplat
89 return {}; 90 return {};
90 } 91 }
91 92
92 VkDescriptorUpdateTemplateCreateInfoKHR ci; 93 return device.GetLogical().CreateDescriptorUpdateTemplateKHR({
93 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 94 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
94 ci.pNext = nullptr; 95 .pNext = nullptr,
95 ci.flags = 0; 96 .flags = 0,
96 ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); 97 .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
97 ci.pDescriptorUpdateEntries = template_entries.data(); 98 .pDescriptorUpdateEntries = template_entries.data(),
98 ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 99 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
99 ci.descriptorSetLayout = *descriptor_set_layout; 100 .descriptorSetLayout = *descriptor_set_layout,
100 ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 101 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
101 ci.pipelineLayout = *layout; 102 .pipelineLayout = *layout,
102 ci.set = DESCRIPTOR_SET; 103 .set = DESCRIPTOR_SET,
103 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); 104 });
104} 105}
105 106
106vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const { 107vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const {
107 device.SaveShader(code); 108 device.SaveShader(code);
108 109
109 VkShaderModuleCreateInfo ci; 110 return device.GetLogical().CreateShaderModule({
110 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 111 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
111 ci.pNext = nullptr; 112 .pNext = nullptr,
112 ci.flags = 0; 113 .flags = 0,
113 ci.codeSize = code.size() * sizeof(u32); 114 .codeSize = code.size() * sizeof(u32),
114 ci.pCode = code.data(); 115 .pCode = code.data(),
115 return device.GetLogical().CreateShaderModule(ci); 116 });
116} 117}
117 118
118vk::Pipeline VKComputePipeline::CreatePipeline() const { 119vk::Pipeline VKComputePipeline::CreatePipeline() const {
119 VkComputePipelineCreateInfo ci; 120
120 VkPipelineShaderStageCreateInfo& stage_ci = ci.stage; 121 VkComputePipelineCreateInfo ci{
121 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 122 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
122 stage_ci.pNext = nullptr; 123 .pNext = nullptr,
123 stage_ci.flags = 0; 124 .flags = 0,
124 stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; 125 .stage =
125 stage_ci.module = *shader_module; 126 {
126 stage_ci.pName = "main"; 127 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
127 stage_ci.pSpecializationInfo = nullptr; 128 .pNext = nullptr,
128 129 .flags = 0,
129 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; 130 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
130 subgroup_size_ci.sType = 131 .module = *shader_module,
131 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; 132 .pName = "main",
132 subgroup_size_ci.pNext = nullptr; 133 .pSpecializationInfo = nullptr,
133 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; 134 },
135 .layout = *layout,
136 .basePipelineHandle = nullptr,
137 .basePipelineIndex = 0,
138 };
139
140 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
141 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
142 .pNext = nullptr,
143 .requiredSubgroupSize = GuestWarpSize,
144 };
134 145
135 if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) { 146 if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) {
136 stage_ci.pNext = &subgroup_size_ci; 147 ci.stage.pNext = &subgroup_size_ci;
137 } 148 }
138 149
139 ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
140 ci.pNext = nullptr;
141 ci.flags = 0;
142 ci.layout = *layout;
143 ci.basePipelineHandle = nullptr;
144 ci.basePipelineIndex = 0;
145 return device.GetLogical().CreateComputePipeline(ci); 150 return device.GetLogical().CreateComputePipeline(ci);
146} 151}
147 152
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
index 9259b618d..ac4a0884e 100644
--- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
@@ -43,27 +43,30 @@ vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() {
43 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, 43 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64},
44 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, 44 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64},
45 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, 45 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64},
46 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}}; 46 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40},
47 47 };
48 VkDescriptorPoolCreateInfo ci; 48
49 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 49 const VkDescriptorPoolCreateInfo ci{
50 ci.pNext = nullptr; 50 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
51 ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; 51 .pNext = nullptr,
52 ci.maxSets = num_sets; 52 .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
53 ci.poolSizeCount = static_cast<u32>(std::size(pool_sizes)); 53 .maxSets = num_sets,
54 ci.pPoolSizes = std::data(pool_sizes); 54 .poolSizeCount = static_cast<u32>(std::size(pool_sizes)),
55 .pPoolSizes = std::data(pool_sizes),
56 };
55 return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci)); 57 return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci));
56} 58}
57 59
58vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout, 60vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout,
59 std::size_t count) { 61 std::size_t count) {
60 const std::vector layout_copies(count, layout); 62 const std::vector layout_copies(count, layout);
61 VkDescriptorSetAllocateInfo ai; 63 VkDescriptorSetAllocateInfo ai{
62 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 64 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
63 ai.pNext = nullptr; 65 .pNext = nullptr,
64 ai.descriptorPool = **active_pool; 66 .descriptorPool = **active_pool,
65 ai.descriptorSetCount = static_cast<u32>(count); 67 .descriptorSetCount = static_cast<u32>(count),
66 ai.pSetLayouts = layout_copies.data(); 68 .pSetLayouts = layout_copies.data(),
69 };
67 70
68 vk::DescriptorSets sets = active_pool->Allocate(ai); 71 vk::DescriptorSets sets = active_pool->Allocate(ai);
69 if (!sets.IsOutOfPoolMemory()) { 72 if (!sets.IsOutOfPoolMemory()) {
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index fdaea4210..26379ee01 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -22,14 +22,21 @@ namespace {
22 22
23namespace Alternatives { 23namespace Alternatives {
24 24
25constexpr std::array Depth24UnormS8_UINT = {VK_FORMAT_D32_SFLOAT_S8_UINT, 25constexpr std::array Depth24UnormS8_UINT{
26 VK_FORMAT_D16_UNORM_S8_UINT, VkFormat{}}; 26 VK_FORMAT_D32_SFLOAT_S8_UINT,
27constexpr std::array Depth16UnormS8_UINT = {VK_FORMAT_D24_UNORM_S8_UINT, 27 VK_FORMAT_D16_UNORM_S8_UINT,
28 VK_FORMAT_D32_SFLOAT_S8_UINT, VkFormat{}}; 28 VkFormat{},
29};
30
31constexpr std::array Depth16UnormS8_UINT{
32 VK_FORMAT_D24_UNORM_S8_UINT,
33 VK_FORMAT_D32_SFLOAT_S8_UINT,
34 VkFormat{},
35};
29 36
30} // namespace Alternatives 37} // namespace Alternatives
31 38
32constexpr std::array REQUIRED_EXTENSIONS = { 39constexpr std::array REQUIRED_EXTENSIONS{
33 VK_KHR_SWAPCHAIN_EXTENSION_NAME, 40 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
34 VK_KHR_16BIT_STORAGE_EXTENSION_NAME, 41 VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
35 VK_KHR_8BIT_STORAGE_EXTENSION_NAME, 42 VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
@@ -169,97 +176,104 @@ bool VKDevice::Create() {
169 const auto queue_cis = GetDeviceQueueCreateInfos(); 176 const auto queue_cis = GetDeviceQueueCreateInfos();
170 const std::vector extensions = LoadExtensions(); 177 const std::vector extensions = LoadExtensions();
171 178
172 VkPhysicalDeviceFeatures2 features2; 179 VkPhysicalDeviceFeatures2 features2{
173 features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 180 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
174 features2.pNext = nullptr; 181 .pNext = nullptr,
182 };
175 const void* first_next = &features2; 183 const void* first_next = &features2;
176 void** next = &features2.pNext; 184 void** next = &features2.pNext;
177 185
178 auto& features = features2.features; 186 features2.features = {
179 features.robustBufferAccess = false; 187 .robustBufferAccess = false,
180 features.fullDrawIndexUint32 = false; 188 .fullDrawIndexUint32 = false,
181 features.imageCubeArray = false; 189 .imageCubeArray = false,
182 features.independentBlend = true; 190 .independentBlend = true,
183 features.geometryShader = true; 191 .geometryShader = true,
184 features.tessellationShader = true; 192 .tessellationShader = true,
185 features.sampleRateShading = false; 193 .sampleRateShading = false,
186 features.dualSrcBlend = false; 194 .dualSrcBlend = false,
187 features.logicOp = false; 195 .logicOp = false,
188 features.multiDrawIndirect = false; 196 .multiDrawIndirect = false,
189 features.drawIndirectFirstInstance = false; 197 .drawIndirectFirstInstance = false,
190 features.depthClamp = true; 198 .depthClamp = true,
191 features.depthBiasClamp = true; 199 .depthBiasClamp = true,
192 features.fillModeNonSolid = false; 200 .fillModeNonSolid = false,
193 features.depthBounds = false; 201 .depthBounds = false,
194 features.wideLines = false; 202 .wideLines = false,
195 features.largePoints = true; 203 .largePoints = true,
196 features.alphaToOne = false; 204 .alphaToOne = false,
197 features.multiViewport = true; 205 .multiViewport = true,
198 features.samplerAnisotropy = true; 206 .samplerAnisotropy = true,
199 features.textureCompressionETC2 = false; 207 .textureCompressionETC2 = false,
200 features.textureCompressionASTC_LDR = is_optimal_astc_supported; 208 .textureCompressionASTC_LDR = is_optimal_astc_supported,
201 features.textureCompressionBC = false; 209 .textureCompressionBC = false,
202 features.occlusionQueryPrecise = true; 210 .occlusionQueryPrecise = true,
203 features.pipelineStatisticsQuery = false; 211 .pipelineStatisticsQuery = false,
204 features.vertexPipelineStoresAndAtomics = true; 212 .vertexPipelineStoresAndAtomics = true,
205 features.fragmentStoresAndAtomics = true; 213 .fragmentStoresAndAtomics = true,
206 features.shaderTessellationAndGeometryPointSize = false; 214 .shaderTessellationAndGeometryPointSize = false,
207 features.shaderImageGatherExtended = true; 215 .shaderImageGatherExtended = true,
208 features.shaderStorageImageExtendedFormats = false; 216 .shaderStorageImageExtendedFormats = false,
209 features.shaderStorageImageMultisample = false; 217 .shaderStorageImageMultisample = false,
210 features.shaderStorageImageReadWithoutFormat = is_formatless_image_load_supported; 218 .shaderStorageImageReadWithoutFormat = is_formatless_image_load_supported,
211 features.shaderStorageImageWriteWithoutFormat = true; 219 .shaderStorageImageWriteWithoutFormat = true,
212 features.shaderUniformBufferArrayDynamicIndexing = false; 220 .shaderUniformBufferArrayDynamicIndexing = false,
213 features.shaderSampledImageArrayDynamicIndexing = false; 221 .shaderSampledImageArrayDynamicIndexing = false,
214 features.shaderStorageBufferArrayDynamicIndexing = false; 222 .shaderStorageBufferArrayDynamicIndexing = false,
215 features.shaderStorageImageArrayDynamicIndexing = false; 223 .shaderStorageImageArrayDynamicIndexing = false,
216 features.shaderClipDistance = false; 224 .shaderClipDistance = false,
217 features.shaderCullDistance = false; 225 .shaderCullDistance = false,
218 features.shaderFloat64 = false; 226 .shaderFloat64 = false,
219 features.shaderInt64 = false; 227 .shaderInt64 = false,
220 features.shaderInt16 = false; 228 .shaderInt16 = false,
221 features.shaderResourceResidency = false; 229 .shaderResourceResidency = false,
222 features.shaderResourceMinLod = false; 230 .shaderResourceMinLod = false,
223 features.sparseBinding = false; 231 .sparseBinding = false,
224 features.sparseResidencyBuffer = false; 232 .sparseResidencyBuffer = false,
225 features.sparseResidencyImage2D = false; 233 .sparseResidencyImage2D = false,
226 features.sparseResidencyImage3D = false; 234 .sparseResidencyImage3D = false,
227 features.sparseResidency2Samples = false; 235 .sparseResidency2Samples = false,
228 features.sparseResidency4Samples = false; 236 .sparseResidency4Samples = false,
229 features.sparseResidency8Samples = false; 237 .sparseResidency8Samples = false,
230 features.sparseResidency16Samples = false; 238 .sparseResidency16Samples = false,
231 features.sparseResidencyAliased = false; 239 .sparseResidencyAliased = false,
232 features.variableMultisampleRate = false; 240 .variableMultisampleRate = false,
233 features.inheritedQueries = false; 241 .inheritedQueries = false,
234 242 };
235 VkPhysicalDevice16BitStorageFeaturesKHR bit16_storage; 243
236 bit16_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR; 244 VkPhysicalDevice16BitStorageFeaturesKHR bit16_storage{
237 bit16_storage.pNext = nullptr; 245 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
238 bit16_storage.storageBuffer16BitAccess = false; 246 .pNext = nullptr,
239 bit16_storage.uniformAndStorageBuffer16BitAccess = true; 247 .storageBuffer16BitAccess = false,
240 bit16_storage.storagePushConstant16 = false; 248 .uniformAndStorageBuffer16BitAccess = true,
241 bit16_storage.storageInputOutput16 = false; 249 .storagePushConstant16 = false,
250 .storageInputOutput16 = false,
251 };
242 SetNext(next, bit16_storage); 252 SetNext(next, bit16_storage);
243 253
244 VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage; 254 VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage{
245 bit8_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR; 255 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
246 bit8_storage.pNext = nullptr; 256 .pNext = nullptr,
247 bit8_storage.storageBuffer8BitAccess = false; 257 .storageBuffer8BitAccess = false,
248 bit8_storage.uniformAndStorageBuffer8BitAccess = true; 258 .uniformAndStorageBuffer8BitAccess = true,
249 bit8_storage.storagePushConstant8 = false; 259 .storagePushConstant8 = false,
260 };
250 SetNext(next, bit8_storage); 261 SetNext(next, bit8_storage);
251 262
252 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset; 263 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{
253 host_query_reset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; 264 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT,
254 host_query_reset.hostQueryReset = true; 265 .hostQueryReset = true,
266 };
255 SetNext(next, host_query_reset); 267 SetNext(next, host_query_reset);
256 268
257 VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8; 269 VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8;
258 if (is_float16_supported) { 270 if (is_float16_supported) {
259 float16_int8.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR; 271 float16_int8 = {
260 float16_int8.pNext = nullptr; 272 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR,
261 float16_int8.shaderFloat16 = true; 273 .pNext = nullptr,
262 float16_int8.shaderInt8 = false; 274 .shaderFloat16 = true,
275 .shaderInt8 = false,
276 };
263 SetNext(next, float16_int8); 277 SetNext(next, float16_int8);
264 } else { 278 } else {
265 LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively"); 279 LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively");
@@ -271,10 +285,11 @@ bool VKDevice::Create() {
271 285
272 VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; 286 VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout;
273 if (khr_uniform_buffer_standard_layout) { 287 if (khr_uniform_buffer_standard_layout) {
274 std430_layout.sType = 288 std430_layout = {
275 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR; 289 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR,
276 std430_layout.pNext = nullptr; 290 .pNext = nullptr,
277 std430_layout.uniformBufferStandardLayout = true; 291 .uniformBufferStandardLayout = true,
292 };
278 SetNext(next, std430_layout); 293 SetNext(next, std430_layout);
279 } else { 294 } else {
280 LOG_INFO(Render_Vulkan, "Device doesn't support packed UBOs"); 295 LOG_INFO(Render_Vulkan, "Device doesn't support packed UBOs");
@@ -282,9 +297,11 @@ bool VKDevice::Create() {
282 297
283 VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8; 298 VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8;
284 if (ext_index_type_uint8) { 299 if (ext_index_type_uint8) {
285 index_type_uint8.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT; 300 index_type_uint8 = {
286 index_type_uint8.pNext = nullptr; 301 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT,
287 index_type_uint8.indexTypeUint8 = true; 302 .pNext = nullptr,
303 .indexTypeUint8 = true,
304 };
288 SetNext(next, index_type_uint8); 305 SetNext(next, index_type_uint8);
289 } else { 306 } else {
290 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes"); 307 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
@@ -292,11 +309,12 @@ bool VKDevice::Create() {
292 309
293 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback; 310 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback;
294 if (ext_transform_feedback) { 311 if (ext_transform_feedback) {
295 transform_feedback.sType = 312 transform_feedback = {
296 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; 313 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
297 transform_feedback.pNext = nullptr; 314 .pNext = nullptr,
298 transform_feedback.transformFeedback = true; 315 .transformFeedback = true,
299 transform_feedback.geometryStreams = true; 316 .geometryStreams = true,
317 };
300 SetNext(next, transform_feedback); 318 SetNext(next, transform_feedback);
301 } else { 319 } else {
302 LOG_INFO(Render_Vulkan, "Device doesn't support transform feedbacks"); 320 LOG_INFO(Render_Vulkan, "Device doesn't support transform feedbacks");
@@ -304,10 +322,12 @@ bool VKDevice::Create() {
304 322
305 VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border; 323 VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border;
306 if (ext_custom_border_color) { 324 if (ext_custom_border_color) {
307 custom_border.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; 325 custom_border = {
308 custom_border.pNext = nullptr; 326 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT,
309 custom_border.customBorderColors = VK_TRUE; 327 .pNext = nullptr,
310 custom_border.customBorderColorWithoutFormat = VK_TRUE; 328 .customBorderColors = VK_TRUE,
329 .customBorderColorWithoutFormat = VK_TRUE,
330 };
311 SetNext(next, custom_border); 331 SetNext(next, custom_border);
312 } else { 332 } else {
313 LOG_INFO(Render_Vulkan, "Device doesn't support custom border colors"); 333 LOG_INFO(Render_Vulkan, "Device doesn't support custom border colors");
@@ -315,9 +335,11 @@ bool VKDevice::Create() {
315 335
316 VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state; 336 VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state;
317 if (ext_extended_dynamic_state) { 337 if (ext_extended_dynamic_state) {
318 dynamic_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; 338 dynamic_state = {
319 dynamic_state.pNext = nullptr; 339 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT,
320 dynamic_state.extendedDynamicState = VK_TRUE; 340 .pNext = nullptr,
341 .extendedDynamicState = VK_TRUE,
342 };
321 SetNext(next, dynamic_state); 343 SetNext(next, dynamic_state);
322 } else { 344 } else {
323 LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state"); 345 LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state");
@@ -331,11 +353,13 @@ bool VKDevice::Create() {
331 if (nv_device_diagnostics_config) { 353 if (nv_device_diagnostics_config) {
332 nsight_aftermath_tracker.Initialize(); 354 nsight_aftermath_tracker.Initialize();
333 355
334 diagnostics_nv.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV; 356 diagnostics_nv = {
335 diagnostics_nv.pNext = &features2; 357 .sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV,
336 diagnostics_nv.flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV | 358 .pNext = &features2,
337 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | 359 .flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV |
338 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV; 360 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV |
361 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV,
362 };
339 first_next = &diagnostics_nv; 363 first_next = &diagnostics_nv;
340 } 364 }
341 365
@@ -704,13 +728,15 @@ void VKDevice::SetupFeatures() {
704} 728}
705 729
706void VKDevice::CollectTelemetryParameters() { 730void VKDevice::CollectTelemetryParameters() {
707 VkPhysicalDeviceDriverPropertiesKHR driver; 731 VkPhysicalDeviceDriverPropertiesKHR driver{
708 driver.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; 732 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
709 driver.pNext = nullptr; 733 .pNext = nullptr,
734 };
710 735
711 VkPhysicalDeviceProperties2KHR properties; 736 VkPhysicalDeviceProperties2KHR properties{
712 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; 737 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
713 properties.pNext = &driver; 738 .pNext = &driver,
739 };
714 physical.GetProperties2KHR(properties); 740 physical.GetProperties2KHR(properties);
715 741
716 driver_id = driver.driverID; 742 driver_id = driver.driverID;
@@ -719,22 +745,24 @@ void VKDevice::CollectTelemetryParameters() {
719 const std::vector extensions = physical.EnumerateDeviceExtensionProperties(); 745 const std::vector extensions = physical.EnumerateDeviceExtensionProperties();
720 reported_extensions.reserve(std::size(extensions)); 746 reported_extensions.reserve(std::size(extensions));
721 for (const auto& extension : extensions) { 747 for (const auto& extension : extensions) {
722 reported_extensions.push_back(extension.extensionName); 748 reported_extensions.emplace_back(extension.extensionName);
723 } 749 }
724} 750}
725 751
726std::vector<VkDeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const { 752std::vector<VkDeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const {
727 static constexpr float QUEUE_PRIORITY = 1.0f; 753 static constexpr float QUEUE_PRIORITY = 1.0f;
728 754
729 std::unordered_set<u32> unique_queue_families = {graphics_family, present_family}; 755 std::unordered_set<u32> unique_queue_families{graphics_family, present_family};
730 std::vector<VkDeviceQueueCreateInfo> queue_cis; 756 std::vector<VkDeviceQueueCreateInfo> queue_cis;
757 queue_cis.reserve(unique_queue_families.size());
731 758
732 for (const u32 queue_family : unique_queue_families) { 759 for (const u32 queue_family : unique_queue_families) {
733 VkDeviceQueueCreateInfo& ci = queue_cis.emplace_back(); 760 auto& ci = queue_cis.emplace_back(VkDeviceQueueCreateInfo{
734 ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 761 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
735 ci.pNext = nullptr; 762 .pNext = nullptr,
736 ci.flags = 0; 763 .flags = 0,
737 ci.queueFamilyIndex = queue_family; 764 .queueFamilyIndex = queue_family,
765 });
738 ci.queueCount = 1; 766 ci.queueCount = 1;
739 ci.pQueuePriorities = &QUEUE_PRIORITY; 767 ci.pQueuePriorities = &QUEUE_PRIORITY;
740 } 768 }
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 844445105..aaf930b90 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -28,15 +28,15 @@ namespace {
28 28
29template <class StencilFace> 29template <class StencilFace>
30VkStencilOpState GetStencilFaceState(const StencilFace& face) { 30VkStencilOpState GetStencilFaceState(const StencilFace& face) {
31 VkStencilOpState state; 31 return {
32 state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()); 32 .failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()),
33 state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()); 33 .passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()),
34 state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()); 34 .depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()),
35 state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()); 35 .compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()),
36 state.compareMask = 0; 36 .compareMask = 0,
37 state.writeMask = 0; 37 .writeMask = 0,
38 state.reference = 0; 38 .reference = 0,
39 return state; 39 };
40} 40}
41 41
42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { 42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
@@ -52,20 +52,21 @@ bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
52} 52}
53 53
54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) { 54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) {
55 union { 55 union Swizzle {
56 u32 raw; 56 u32 raw;
57 BitField<0, 3, Maxwell::ViewportSwizzle> x; 57 BitField<0, 3, Maxwell::ViewportSwizzle> x;
58 BitField<4, 3, Maxwell::ViewportSwizzle> y; 58 BitField<4, 3, Maxwell::ViewportSwizzle> y;
59 BitField<8, 3, Maxwell::ViewportSwizzle> z; 59 BitField<8, 3, Maxwell::ViewportSwizzle> z;
60 BitField<12, 3, Maxwell::ViewportSwizzle> w; 60 BitField<12, 3, Maxwell::ViewportSwizzle> w;
61 } const unpacked{swizzle}; 61 };
62 62 const Swizzle unpacked{swizzle};
63 VkViewportSwizzleNV result; 63
64 result.x = MaxwellToVK::ViewportSwizzle(unpacked.x); 64 return {
65 result.y = MaxwellToVK::ViewportSwizzle(unpacked.y); 65 .x = MaxwellToVK::ViewportSwizzle(unpacked.x),
66 result.z = MaxwellToVK::ViewportSwizzle(unpacked.z); 66 .y = MaxwellToVK::ViewportSwizzle(unpacked.y),
67 result.w = MaxwellToVK::ViewportSwizzle(unpacked.w); 67 .z = MaxwellToVK::ViewportSwizzle(unpacked.z),
68 return result; 68 .w = MaxwellToVK::ViewportSwizzle(unpacked.w),
69 };
69} 70}
70 71
71} // Anonymous namespace 72} // Anonymous namespace
@@ -100,24 +101,26 @@ VkDescriptorSet VKGraphicsPipeline::CommitDescriptorSet() {
100 101
101vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout( 102vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout(
102 vk::Span<VkDescriptorSetLayoutBinding> bindings) const { 103 vk::Span<VkDescriptorSetLayoutBinding> bindings) const {
103 VkDescriptorSetLayoutCreateInfo ci; 104 const VkDescriptorSetLayoutCreateInfo ci{
104 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 105 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
105 ci.pNext = nullptr; 106 .pNext = nullptr,
106 ci.flags = 0; 107 .flags = 0,
107 ci.bindingCount = bindings.size(); 108 .bindingCount = bindings.size(),
108 ci.pBindings = bindings.data(); 109 .pBindings = bindings.data(),
110 };
109 return device.GetLogical().CreateDescriptorSetLayout(ci); 111 return device.GetLogical().CreateDescriptorSetLayout(ci);
110} 112}
111 113
112vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const { 114vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const {
113 VkPipelineLayoutCreateInfo ci; 115 const VkPipelineLayoutCreateInfo ci{
114 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 116 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
115 ci.pNext = nullptr; 117 .pNext = nullptr,
116 ci.flags = 0; 118 .flags = 0,
117 ci.setLayoutCount = 1; 119 .setLayoutCount = 1,
118 ci.pSetLayouts = descriptor_set_layout.address(); 120 .pSetLayouts = descriptor_set_layout.address(),
119 ci.pushConstantRangeCount = 0; 121 .pushConstantRangeCount = 0,
120 ci.pPushConstantRanges = nullptr; 122 .pPushConstantRanges = nullptr,
123 };
121 return device.GetLogical().CreatePipelineLayout(ci); 124 return device.GetLogical().CreatePipelineLayout(ci);
122} 125}
123 126
@@ -136,26 +139,28 @@ vk::DescriptorUpdateTemplateKHR VKGraphicsPipeline::CreateDescriptorUpdateTempla
136 return {}; 139 return {};
137 } 140 }
138 141
139 VkDescriptorUpdateTemplateCreateInfoKHR ci; 142 const VkDescriptorUpdateTemplateCreateInfoKHR ci{
140 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 143 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
141 ci.pNext = nullptr; 144 .pNext = nullptr,
142 ci.flags = 0; 145 .flags = 0,
143 ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); 146 .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
144 ci.pDescriptorUpdateEntries = template_entries.data(); 147 .pDescriptorUpdateEntries = template_entries.data(),
145 ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 148 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
146 ci.descriptorSetLayout = *descriptor_set_layout; 149 .descriptorSetLayout = *descriptor_set_layout,
147 ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 150 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
148 ci.pipelineLayout = *layout; 151 .pipelineLayout = *layout,
149 ci.set = DESCRIPTOR_SET; 152 .set = DESCRIPTOR_SET,
153 };
150 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); 154 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci);
151} 155}
152 156
153std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( 157std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
154 const SPIRVProgram& program) const { 158 const SPIRVProgram& program) const {
155 VkShaderModuleCreateInfo ci; 159 VkShaderModuleCreateInfo ci{
156 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 160 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
157 ci.pNext = nullptr; 161 .pNext = nullptr,
158 ci.flags = 0; 162 .flags = 0,
163 };
159 164
160 std::vector<vk::ShaderModule> modules; 165 std::vector<vk::ShaderModule> modules;
161 modules.reserve(Maxwell::MaxShaderStage); 166 modules.reserve(Maxwell::MaxShaderStage);
@@ -204,15 +209,17 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
204 const bool instanced = state.binding_divisors[index] != 0; 209 const bool instanced = state.binding_divisors[index] != 0;
205 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; 210 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
206 211
207 auto& vertex_binding = vertex_bindings.emplace_back(); 212 vertex_bindings.push_back({
208 vertex_binding.binding = static_cast<u32>(index); 213 .binding = static_cast<u32>(index),
209 vertex_binding.stride = binding.stride; 214 .stride = binding.stride,
210 vertex_binding.inputRate = rate; 215 .inputRate = rate,
216 });
211 217
212 if (instanced) { 218 if (instanced) {
213 auto& binding_divisor = vertex_binding_divisors.emplace_back(); 219 vertex_binding_divisors.push_back({
214 binding_divisor.binding = static_cast<u32>(index); 220 .binding = static_cast<u32>(index),
215 binding_divisor.divisor = state.binding_divisors[index]; 221 .divisor = state.binding_divisors[index],
222 });
216 } 223 }
217 } 224 }
218 225
@@ -227,116 +234,132 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
227 // Skip attributes not used by the vertex shaders. 234 // Skip attributes not used by the vertex shaders.
228 continue; 235 continue;
229 } 236 }
230 auto& vertex_attribute = vertex_attributes.emplace_back(); 237 vertex_attributes.push_back({
231 vertex_attribute.location = static_cast<u32>(index); 238 .location = static_cast<u32>(index),
232 vertex_attribute.binding = attribute.buffer; 239 .binding = attribute.buffer,
233 vertex_attribute.format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()); 240 .format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()),
234 vertex_attribute.offset = attribute.offset; 241 .offset = attribute.offset,
242 });
235 } 243 }
236 244
237 VkPipelineVertexInputStateCreateInfo vertex_input_ci; 245 VkPipelineVertexInputStateCreateInfo vertex_input_ci{
238 vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 246 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
239 vertex_input_ci.pNext = nullptr; 247 .pNext = nullptr,
240 vertex_input_ci.flags = 0; 248 .flags = 0,
241 vertex_input_ci.vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()); 249 .vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()),
242 vertex_input_ci.pVertexBindingDescriptions = vertex_bindings.data(); 250 .pVertexBindingDescriptions = vertex_bindings.data(),
243 vertex_input_ci.vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()); 251 .vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()),
244 vertex_input_ci.pVertexAttributeDescriptions = vertex_attributes.data(); 252 .pVertexAttributeDescriptions = vertex_attributes.data(),
245 253 };
246 VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci; 254
247 input_divisor_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; 255 const VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci{
248 input_divisor_ci.pNext = nullptr; 256 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT,
249 input_divisor_ci.vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()); 257 .pNext = nullptr,
250 input_divisor_ci.pVertexBindingDivisors = vertex_binding_divisors.data(); 258 .vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()),
259 .pVertexBindingDivisors = vertex_binding_divisors.data(),
260 };
251 if (!vertex_binding_divisors.empty()) { 261 if (!vertex_binding_divisors.empty()) {
252 vertex_input_ci.pNext = &input_divisor_ci; 262 vertex_input_ci.pNext = &input_divisor_ci;
253 } 263 }
254 264
255 VkPipelineInputAssemblyStateCreateInfo input_assembly_ci; 265 const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
256 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 266 const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
257 input_assembly_ci.pNext = nullptr; 267 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
258 input_assembly_ci.flags = 0; 268 .pNext = nullptr,
259 input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()); 269 .flags = 0,
260 input_assembly_ci.primitiveRestartEnable = 270 .topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
261 state.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology); 271 .primitiveRestartEnable = state.primitive_restart_enable != 0 &&
262 272 SupportsPrimitiveRestart(input_assembly_topology),
263 VkPipelineTessellationStateCreateInfo tessellation_ci; 273 };
264 tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; 274
265 tessellation_ci.pNext = nullptr; 275 const VkPipelineTessellationStateCreateInfo tessellation_ci{
266 tessellation_ci.flags = 0; 276 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
267 tessellation_ci.patchControlPoints = state.patch_control_points_minus_one.Value() + 1; 277 .pNext = nullptr,
268 278 .flags = 0,
269 VkPipelineViewportStateCreateInfo viewport_ci; 279 .patchControlPoints = state.patch_control_points_minus_one.Value() + 1,
270 viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 280 };
271 viewport_ci.pNext = nullptr; 281
272 viewport_ci.flags = 0; 282 VkPipelineViewportStateCreateInfo viewport_ci{
273 viewport_ci.viewportCount = Maxwell::NumViewports; 283 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
274 viewport_ci.pViewports = nullptr; 284 .pNext = nullptr,
275 viewport_ci.scissorCount = Maxwell::NumViewports; 285 .flags = 0,
276 viewport_ci.pScissors = nullptr; 286 .viewportCount = Maxwell::NumViewports,
287 .pViewports = nullptr,
288 .scissorCount = Maxwell::NumViewports,
289 .pScissors = nullptr,
290 };
277 291
278 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles; 292 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
279 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(), 293 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(),
280 UnpackViewportSwizzle); 294 UnpackViewportSwizzle);
281 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci; 295 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
282 swizzle_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV; 296 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
283 swizzle_ci.pNext = nullptr; 297 .pNext = nullptr,
284 swizzle_ci.flags = 0; 298 .flags = 0,
285 swizzle_ci.viewportCount = Maxwell::NumViewports; 299 .viewportCount = Maxwell::NumViewports,
286 swizzle_ci.pViewportSwizzles = swizzles.data(); 300 .pViewportSwizzles = swizzles.data(),
301 };
287 if (device.IsNvViewportSwizzleSupported()) { 302 if (device.IsNvViewportSwizzleSupported()) {
288 viewport_ci.pNext = &swizzle_ci; 303 viewport_ci.pNext = &swizzle_ci;
289 } 304 }
290 305
291 VkPipelineRasterizationStateCreateInfo rasterization_ci; 306 const VkPipelineRasterizationStateCreateInfo rasterization_ci{
292 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 307 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
293 rasterization_ci.pNext = nullptr; 308 .pNext = nullptr,
294 rasterization_ci.flags = 0; 309 .flags = 0,
295 rasterization_ci.depthClampEnable = state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE; 310 .depthClampEnable =
296 rasterization_ci.rasterizerDiscardEnable = state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE; 311 static_cast<VkBool32>(state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
297 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 312 .rasterizerDiscardEnable =
298 rasterization_ci.cullMode = 313 static_cast<VkBool32>(state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
299 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE; 314 .polygonMode = VK_POLYGON_MODE_FILL,
300 rasterization_ci.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()); 315 .cullMode =
301 rasterization_ci.depthBiasEnable = state.depth_bias_enable; 316 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE,
302 rasterization_ci.depthBiasConstantFactor = 0.0f; 317 .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
303 rasterization_ci.depthBiasClamp = 0.0f; 318 .depthBiasEnable = state.depth_bias_enable,
304 rasterization_ci.depthBiasSlopeFactor = 0.0f; 319 .depthBiasConstantFactor = 0.0f,
305 rasterization_ci.lineWidth = 1.0f; 320 .depthBiasClamp = 0.0f,
306 321 .depthBiasSlopeFactor = 0.0f,
307 VkPipelineMultisampleStateCreateInfo multisample_ci; 322 .lineWidth = 1.0f,
308 multisample_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 323 };
309 multisample_ci.pNext = nullptr; 324
310 multisample_ci.flags = 0; 325 const VkPipelineMultisampleStateCreateInfo multisample_ci{
311 multisample_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 326 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
312 multisample_ci.sampleShadingEnable = VK_FALSE; 327 .pNext = nullptr,
313 multisample_ci.minSampleShading = 0.0f; 328 .flags = 0,
314 multisample_ci.pSampleMask = nullptr; 329 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
315 multisample_ci.alphaToCoverageEnable = VK_FALSE; 330 .sampleShadingEnable = VK_FALSE,
316 multisample_ci.alphaToOneEnable = VK_FALSE; 331 .minSampleShading = 0.0f,
317 332 .pSampleMask = nullptr,
318 VkPipelineDepthStencilStateCreateInfo depth_stencil_ci; 333 .alphaToCoverageEnable = VK_FALSE,
319 depth_stencil_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 334 .alphaToOneEnable = VK_FALSE,
320 depth_stencil_ci.pNext = nullptr; 335 };
321 depth_stencil_ci.flags = 0; 336
322 depth_stencil_ci.depthTestEnable = dynamic.depth_test_enable; 337 const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
323 depth_stencil_ci.depthWriteEnable = dynamic.depth_write_enable; 338 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
324 depth_stencil_ci.depthCompareOp = dynamic.depth_test_enable 339 .pNext = nullptr,
325 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc()) 340 .flags = 0,
326 : VK_COMPARE_OP_ALWAYS; 341 .depthTestEnable = dynamic.depth_test_enable,
327 depth_stencil_ci.depthBoundsTestEnable = dynamic.depth_bounds_enable; 342 .depthWriteEnable = dynamic.depth_write_enable,
328 depth_stencil_ci.stencilTestEnable = dynamic.stencil_enable; 343 .depthCompareOp = dynamic.depth_test_enable
329 depth_stencil_ci.front = GetStencilFaceState(dynamic.front); 344 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc())
330 depth_stencil_ci.back = GetStencilFaceState(dynamic.back); 345 : VK_COMPARE_OP_ALWAYS,
331 depth_stencil_ci.minDepthBounds = 0.0f; 346 .depthBoundsTestEnable = dynamic.depth_bounds_enable,
332 depth_stencil_ci.maxDepthBounds = 0.0f; 347 .stencilTestEnable = dynamic.stencil_enable,
348 .front = GetStencilFaceState(dynamic.front),
349 .back = GetStencilFaceState(dynamic.back),
350 .minDepthBounds = 0.0f,
351 .maxDepthBounds = 0.0f,
352 };
333 353
334 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments; 354 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
335 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments); 355 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments);
336 for (std::size_t index = 0; index < num_attachments; ++index) { 356 for (std::size_t index = 0; index < num_attachments; ++index) {
337 static constexpr std::array COMPONENT_TABLE = { 357 static constexpr std::array COMPONENT_TABLE{
338 VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, 358 VK_COLOR_COMPONENT_R_BIT,
339 VK_COLOR_COMPONENT_A_BIT}; 359 VK_COLOR_COMPONENT_G_BIT,
360 VK_COLOR_COMPONENT_B_BIT,
361 VK_COLOR_COMPONENT_A_BIT,
362 };
340 const auto& blend = state.attachments[index]; 363 const auto& blend = state.attachments[index];
341 364
342 VkColorComponentFlags color_components = 0; 365 VkColorComponentFlags color_components = 0;
@@ -346,35 +369,36 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
346 } 369 }
347 } 370 }
348 371
349 VkPipelineColorBlendAttachmentState& attachment = cb_attachments[index]; 372 cb_attachments[index] = {
350 attachment.blendEnable = blend.enable != 0; 373 .blendEnable = blend.enable != 0,
351 attachment.srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()); 374 .srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()),
352 attachment.dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()); 375 .dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()),
353 attachment.colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()); 376 .colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()),
354 attachment.srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()); 377 .srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()),
355 attachment.dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()); 378 .dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()),
356 attachment.alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()); 379 .alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()),
357 attachment.colorWriteMask = color_components; 380 .colorWriteMask = color_components,
381 };
358 } 382 }
359 383
360 VkPipelineColorBlendStateCreateInfo color_blend_ci; 384 const VkPipelineColorBlendStateCreateInfo color_blend_ci{
361 color_blend_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 385 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
362 color_blend_ci.pNext = nullptr; 386 .pNext = nullptr,
363 color_blend_ci.flags = 0; 387 .flags = 0,
364 color_blend_ci.logicOpEnable = VK_FALSE; 388 .logicOpEnable = VK_FALSE,
365 color_blend_ci.logicOp = VK_LOGIC_OP_COPY; 389 .logicOp = VK_LOGIC_OP_COPY,
366 color_blend_ci.attachmentCount = static_cast<u32>(num_attachments); 390 .attachmentCount = static_cast<u32>(num_attachments),
367 color_blend_ci.pAttachments = cb_attachments.data(); 391 .pAttachments = cb_attachments.data(),
368 std::memset(color_blend_ci.blendConstants, 0, sizeof(color_blend_ci.blendConstants)); 392 };
369 393
370 std::vector dynamic_states = { 394 std::vector dynamic_states{
371 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, 395 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
372 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS, 396 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
373 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 397 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
374 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, 398 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
375 }; 399 };
376 if (device.IsExtExtendedDynamicStateSupported()) { 400 if (device.IsExtExtendedDynamicStateSupported()) {
377 static constexpr std::array extended = { 401 static constexpr std::array extended{
378 VK_DYNAMIC_STATE_CULL_MODE_EXT, 402 VK_DYNAMIC_STATE_CULL_MODE_EXT,
379 VK_DYNAMIC_STATE_FRONT_FACE_EXT, 403 VK_DYNAMIC_STATE_FRONT_FACE_EXT,
380 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT, 404 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
@@ -389,18 +413,19 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
389 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); 413 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
390 } 414 }
391 415
392 VkPipelineDynamicStateCreateInfo dynamic_state_ci; 416 const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
393 dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 417 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
394 dynamic_state_ci.pNext = nullptr; 418 .pNext = nullptr,
395 dynamic_state_ci.flags = 0; 419 .flags = 0,
396 dynamic_state_ci.dynamicStateCount = static_cast<u32>(dynamic_states.size()); 420 .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
397 dynamic_state_ci.pDynamicStates = dynamic_states.data(); 421 .pDynamicStates = dynamic_states.data(),
422 };
398 423
399 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; 424 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
400 subgroup_size_ci.sType = 425 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
401 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; 426 .pNext = nullptr,
402 subgroup_size_ci.pNext = nullptr; 427 .requiredSubgroupSize = GuestWarpSize,
403 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; 428 };
404 429
405 std::vector<VkPipelineShaderStageCreateInfo> shader_stages; 430 std::vector<VkPipelineShaderStageCreateInfo> shader_stages;
406 std::size_t module_index = 0; 431 std::size_t module_index = 0;
@@ -408,6 +433,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
408 if (!program[stage]) { 433 if (!program[stage]) {
409 continue; 434 continue;
410 } 435 }
436
411 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back(); 437 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back();
412 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 438 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
413 stage_ci.pNext = nullptr; 439 stage_ci.pNext = nullptr;
@@ -422,26 +448,27 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
422 } 448 }
423 } 449 }
424 450
425 VkGraphicsPipelineCreateInfo ci; 451 const VkGraphicsPipelineCreateInfo ci{
426 ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 452 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
427 ci.pNext = nullptr; 453 .pNext = nullptr,
428 ci.flags = 0; 454 .flags = 0,
429 ci.stageCount = static_cast<u32>(shader_stages.size()); 455 .stageCount = static_cast<u32>(shader_stages.size()),
430 ci.pStages = shader_stages.data(); 456 .pStages = shader_stages.data(),
431 ci.pVertexInputState = &vertex_input_ci; 457 .pVertexInputState = &vertex_input_ci,
432 ci.pInputAssemblyState = &input_assembly_ci; 458 .pInputAssemblyState = &input_assembly_ci,
433 ci.pTessellationState = &tessellation_ci; 459 .pTessellationState = &tessellation_ci,
434 ci.pViewportState = &viewport_ci; 460 .pViewportState = &viewport_ci,
435 ci.pRasterizationState = &rasterization_ci; 461 .pRasterizationState = &rasterization_ci,
436 ci.pMultisampleState = &multisample_ci; 462 .pMultisampleState = &multisample_ci,
437 ci.pDepthStencilState = &depth_stencil_ci; 463 .pDepthStencilState = &depth_stencil_ci,
438 ci.pColorBlendState = &color_blend_ci; 464 .pColorBlendState = &color_blend_ci,
439 ci.pDynamicState = &dynamic_state_ci; 465 .pDynamicState = &dynamic_state_ci,
440 ci.layout = *layout; 466 .layout = *layout,
441 ci.renderPass = renderpass; 467 .renderPass = renderpass,
442 ci.subpass = 0; 468 .subpass = 0,
443 ci.basePipelineHandle = nullptr; 469 .basePipelineHandle = nullptr,
444 ci.basePipelineIndex = 0; 470 .basePipelineIndex = 0,
471 };
445 return device.GetLogical().CreateGraphicsPipeline(ci); 472 return device.GetLogical().CreateGraphicsPipeline(ci);
446} 473}
447 474
diff --git a/src/video_core/renderer_vulkan/vk_image.cpp b/src/video_core/renderer_vulkan/vk_image.cpp
index 9bceb3861..1c418ea17 100644
--- a/src/video_core/renderer_vulkan/vk_image.cpp
+++ b/src/video_core/renderer_vulkan/vk_image.cpp
@@ -102,21 +102,29 @@ bool VKImage::HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num
102 102
103void VKImage::CreatePresentView() { 103void VKImage::CreatePresentView() {
104 // Image type has to be 2D to be presented. 104 // Image type has to be 2D to be presented.
105 VkImageViewCreateInfo image_view_ci; 105 present_view = device.GetLogical().CreateImageView({
106 image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 106 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
107 image_view_ci.pNext = nullptr; 107 .pNext = nullptr,
108 image_view_ci.flags = 0; 108 .flags = 0,
109 image_view_ci.image = *image; 109 .image = *image,
110 image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 110 .viewType = VK_IMAGE_VIEW_TYPE_2D,
111 image_view_ci.format = format; 111 .format = format,
112 image_view_ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 112 .components =
113 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 113 {
114 image_view_ci.subresourceRange.aspectMask = aspect_mask; 114 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
115 image_view_ci.subresourceRange.baseMipLevel = 0; 115 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
116 image_view_ci.subresourceRange.levelCount = 1; 116 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
117 image_view_ci.subresourceRange.baseArrayLayer = 0; 117 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
118 image_view_ci.subresourceRange.layerCount = 1; 118 },
119 present_view = device.GetLogical().CreateImageView(image_view_ci); 119 .subresourceRange =
120 {
121 .aspectMask = aspect_mask,
122 .baseMipLevel = 0,
123 .levelCount = 1,
124 .baseArrayLayer = 0,
125 .layerCount = 1,
126 },
127 });
120} 128}
121 129
122VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept { 130VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept {
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.cpp b/src/video_core/renderer_vulkan/vk_memory_manager.cpp
index b4c650a63..24c8960ac 100644
--- a/src/video_core/renderer_vulkan/vk_memory_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_memory_manager.cpp
@@ -178,13 +178,12 @@ bool VKMemoryManager::AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 t
178 }(); 178 }();
179 179
180 // Try to allocate found type. 180 // Try to allocate found type.
181 VkMemoryAllocateInfo memory_ai; 181 vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({
182 memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 182 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
183 memory_ai.pNext = nullptr; 183 .pNext = nullptr,
184 memory_ai.allocationSize = size; 184 .allocationSize = size,
185 memory_ai.memoryTypeIndex = type; 185 .memoryTypeIndex = type,
186 186 });
187 vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory(memory_ai);
188 if (!memory) { 187 if (!memory) {
189 LOG_CRITICAL(Render_Vulkan, "Device allocation failed!"); 188 LOG_CRITICAL(Render_Vulkan, "Device allocation failed!");
190 return false; 189 return false;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 3da835324..42b3a744c 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -88,12 +88,13 @@ void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& bindi
88 // Combined image samplers can be arrayed. 88 // Combined image samplers can be arrayed.
89 count = container[i].size; 89 count = container[i].size;
90 } 90 }
91 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); 91 bindings.push_back({
92 entry.binding = binding++; 92 .binding = binding++,
93 entry.descriptorType = descriptor_type; 93 .descriptorType = descriptor_type,
94 entry.descriptorCount = count; 94 .descriptorCount = count,
95 entry.stageFlags = stage_flags; 95 .stageFlags = stage_flags,
96 entry.pImmutableSamplers = nullptr; 96 .pImmutableSamplers = nullptr,
97 });
97 } 98 }
98} 99}
99 100
@@ -259,10 +260,10 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
259 } 260 }
260 } 261 }
261 262
262 Specialization specialization; 263 const Specialization specialization{
263 specialization.workgroup_size = key.workgroup_size; 264 .workgroup_size = key.workgroup_size,
264 specialization.shared_memory_size = key.shared_memory_size; 265 .shared_memory_size = key.shared_memory_size,
265 266 };
266 const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute, 267 const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute,
267 shader->GetRegistry(), specialization), 268 shader->GetRegistry(), specialization),
268 shader->GetEntries()}; 269 shader->GetEntries()};
@@ -370,13 +371,14 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
370 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) { 371 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) {
371 for (u32 i = 0; i < count; ++i) { 372 for (u32 i = 0; i < count; ++i) {
372 const u32 num_samplers = container[i].size; 373 const u32 num_samplers = container[i].size;
373 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 374 template_entries.push_back({
374 entry.dstBinding = binding; 375 .dstBinding = binding,
375 entry.dstArrayElement = 0; 376 .dstArrayElement = 0,
376 entry.descriptorCount = num_samplers; 377 .descriptorCount = num_samplers,
377 entry.descriptorType = descriptor_type; 378 .descriptorType = descriptor_type,
378 entry.offset = offset; 379 .offset = offset,
379 entry.stride = entry_size; 380 .stride = entry_size,
381 });
380 382
381 ++binding; 383 ++binding;
382 offset += num_samplers * entry_size; 384 offset += num_samplers * entry_size;
@@ -389,22 +391,24 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
389 // Nvidia has a bug where updating multiple texels at once causes the driver to crash. 391 // Nvidia has a bug where updating multiple texels at once causes the driver to crash.
390 // Note: Fixed in driver Windows 443.24, Linux 440.66.15 392 // Note: Fixed in driver Windows 443.24, Linux 440.66.15
391 for (u32 i = 0; i < count; ++i) { 393 for (u32 i = 0; i < count; ++i) {
392 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 394 template_entries.push_back({
393 entry.dstBinding = binding + i; 395 .dstBinding = binding + i,
394 entry.dstArrayElement = 0; 396 .dstArrayElement = 0,
395 entry.descriptorCount = 1; 397 .descriptorCount = 1,
396 entry.descriptorType = descriptor_type; 398 .descriptorType = descriptor_type,
397 entry.offset = static_cast<std::size_t>(offset + i * entry_size); 399 .offset = static_cast<std::size_t>(offset + i * entry_size),
398 entry.stride = entry_size; 400 .stride = entry_size,
401 });
399 } 402 }
400 } else if (count > 0) { 403 } else if (count > 0) {
401 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 404 template_entries.push_back({
402 entry.dstBinding = binding; 405 .dstBinding = binding,
403 entry.dstArrayElement = 0; 406 .dstArrayElement = 0,
404 entry.descriptorCount = count; 407 .descriptorCount = count,
405 entry.descriptorType = descriptor_type; 408 .descriptorType = descriptor_type,
406 entry.offset = offset; 409 .offset = offset,
407 entry.stride = entry_size; 410 .stride = entry_size,
411 });
408 } 412 }
409 offset += count * entry_size; 413 offset += count * entry_size;
410 binding += count; 414 binding += count;
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index bc91c48cc..6cd63d090 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -47,14 +47,14 @@ std::pair<VkQueryPool, u32> QueryPool::Commit(VKFence& fence) {
47void QueryPool::Allocate(std::size_t begin, std::size_t end) { 47void QueryPool::Allocate(std::size_t begin, std::size_t end) {
48 usage.resize(end); 48 usage.resize(end);
49 49
50 VkQueryPoolCreateInfo query_pool_ci; 50 pools.push_back(device->GetLogical().CreateQueryPool({
51 query_pool_ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; 51 .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
52 query_pool_ci.pNext = nullptr; 52 .pNext = nullptr,
53 query_pool_ci.flags = 0; 53 .flags = 0,
54 query_pool_ci.queryType = GetTarget(type); 54 .queryType = GetTarget(type),
55 query_pool_ci.queryCount = static_cast<u32>(end - begin); 55 .queryCount = static_cast<u32>(end - begin),
56 query_pool_ci.pipelineStatistics = 0; 56 .pipelineStatistics = 0,
57 pools.push_back(device->GetLogical().CreateQueryPool(query_pool_ci)); 57 }));
58} 58}
59 59
60void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { 60void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 7625871c2..31e44aa2b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -64,20 +64,22 @@ VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::si
64 const auto& src = regs.viewport_transform[index]; 64 const auto& src = regs.viewport_transform[index];
65 const float width = src.scale_x * 2.0f; 65 const float width = src.scale_x * 2.0f;
66 const float height = src.scale_y * 2.0f; 66 const float height = src.scale_y * 2.0f;
67 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
67 68
68 VkViewport viewport; 69 VkViewport viewport{
69 viewport.x = src.translate_x - src.scale_x; 70 .x = src.translate_x - src.scale_x,
70 viewport.y = src.translate_y - src.scale_y; 71 .y = src.translate_y - src.scale_y,
71 viewport.width = width != 0.0f ? width : 1.0f; 72 .width = width != 0.0f ? width : 1.0f,
72 viewport.height = height != 0.0f ? height : 1.0f; 73 .height = height != 0.0f ? height : 1.0f,
74 .minDepth = src.translate_z - src.scale_z * reduce_z,
75 .maxDepth = src.translate_z + src.scale_z,
76 };
73 77
74 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
75 viewport.minDepth = src.translate_z - src.scale_z * reduce_z;
76 viewport.maxDepth = src.translate_z + src.scale_z;
77 if (!device.IsExtDepthRangeUnrestrictedSupported()) { 78 if (!device.IsExtDepthRangeUnrestrictedSupported()) {
78 viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); 79 viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f);
79 viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); 80 viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f);
80 } 81 }
82
81 return viewport; 83 return viewport;
82} 84}
83 85
@@ -508,10 +510,11 @@ void RasterizerVulkan::Clear() {
508 510
509 const u32 color_attachment = regs.clear_buffers.RT; 511 const u32 color_attachment = regs.clear_buffers.RT;
510 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 512 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
511 VkClearAttachment attachment; 513 const VkClearAttachment attachment{
512 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 514 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
513 attachment.colorAttachment = color_attachment; 515 .colorAttachment = color_attachment,
514 attachment.clearValue = clear_value; 516 .clearValue = clear_value,
517 };
515 cmdbuf.ClearAttachments(attachment, clear_rect); 518 cmdbuf.ClearAttachments(attachment, clear_rect);
516 }); 519 });
517 } 520 }
@@ -551,13 +554,16 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
551 query_cache.UpdateCounters(); 554 query_cache.UpdateCounters();
552 555
553 const auto& launch_desc = system.GPU().KeplerCompute().launch_description; 556 const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
554 ComputePipelineCacheKey key; 557 auto& pipeline = pipeline_cache.GetComputePipeline({
555 key.shader = code_addr; 558 .shader = code_addr,
556 key.shared_memory_size = launch_desc.shared_alloc; 559 .shared_memory_size = launch_desc.shared_alloc,
557 key.workgroup_size = {launch_desc.block_dim_x, launch_desc.block_dim_y, 560 .workgroup_size =
558 launch_desc.block_dim_z}; 561 {
559 562 launch_desc.block_dim_x,
560 auto& pipeline = pipeline_cache.GetComputePipeline(key); 563 launch_desc.block_dim_y,
564 launch_desc.block_dim_z,
565 },
566 });
561 567
562 // Compute dispatches can't be executed inside a renderpass 568 // Compute dispatches can't be executed inside a renderpass
563 scheduler.RequestOutsideRenderPassOperationContext(); 569 scheduler.RequestOutsideRenderPassOperationContext();
@@ -841,17 +847,17 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers(
841 const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); 847 const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key);
842 auto& framebuffer = fbentry->second; 848 auto& framebuffer = fbentry->second;
843 if (is_cache_miss) { 849 if (is_cache_miss) {
844 VkFramebufferCreateInfo framebuffer_ci; 850 framebuffer = device.GetLogical().CreateFramebuffer({
845 framebuffer_ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 851 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
846 framebuffer_ci.pNext = nullptr; 852 .pNext = nullptr,
847 framebuffer_ci.flags = 0; 853 .flags = 0,
848 framebuffer_ci.renderPass = key.renderpass; 854 .renderPass = key.renderpass,
849 framebuffer_ci.attachmentCount = static_cast<u32>(key.views.size()); 855 .attachmentCount = static_cast<u32>(key.views.size()),
850 framebuffer_ci.pAttachments = key.views.data(); 856 .pAttachments = key.views.data(),
851 framebuffer_ci.width = key.width; 857 .width = key.width,
852 framebuffer_ci.height = key.height; 858 .height = key.height,
853 framebuffer_ci.layers = key.layers; 859 .layers = key.layers,
854 framebuffer = device.GetLogical().CreateFramebuffer(framebuffer_ci); 860 });
855 } 861 }
856 862
857 return {*framebuffer, VkExtent2D{key.width, key.height}}; 863 return {*framebuffer, VkExtent2D{key.width, key.height}};
@@ -1553,17 +1559,17 @@ VkBuffer RasterizerVulkan::DefaultBuffer() {
1553 return *default_buffer; 1559 return *default_buffer;
1554 } 1560 }
1555 1561
1556 VkBufferCreateInfo ci; 1562 default_buffer = device.GetLogical().CreateBuffer({
1557 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 1563 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1558 ci.pNext = nullptr; 1564 .pNext = nullptr,
1559 ci.flags = 0; 1565 .flags = 0,
1560 ci.size = DEFAULT_BUFFER_SIZE; 1566 .size = DEFAULT_BUFFER_SIZE,
1561 ci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | 1567 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
1562 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 1568 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
1563 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 1569 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1564 ci.queueFamilyIndexCount = 0; 1570 .queueFamilyIndexCount = 0,
1565 ci.pQueueFamilyIndices = nullptr; 1571 .pQueueFamilyIndices = nullptr,
1566 default_buffer = device.GetLogical().CreateBuffer(ci); 1572 });
1567 default_buffer_commit = memory_manager.Commit(default_buffer, false); 1573 default_buffer_commit = memory_manager.Commit(default_buffer, false);
1568 1574
1569 scheduler.RequestOutsideRenderPassOperationContext(); 1575 scheduler.RequestOutsideRenderPassOperationContext();
diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
index 3f71d005e..80284cf92 100644
--- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
@@ -39,10 +39,14 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) {
39 39
40vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { 40vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const {
41 using namespace VideoCore::Surface; 41 using namespace VideoCore::Surface;
42 const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
43
42 std::vector<VkAttachmentDescription> descriptors; 44 std::vector<VkAttachmentDescription> descriptors;
45 descriptors.reserve(num_attachments);
46
43 std::vector<VkAttachmentReference> color_references; 47 std::vector<VkAttachmentReference> color_references;
48 color_references.reserve(num_attachments);
44 49
45 const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
46 for (std::size_t rt = 0; rt < num_attachments; ++rt) { 50 for (std::size_t rt = 0; rt < num_attachments; ++rt) {
47 const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]); 51 const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]);
48 const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format); 52 const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format);
@@ -54,20 +58,22 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
54 const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0 58 const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0
55 ? VK_IMAGE_LAYOUT_GENERAL 59 ? VK_IMAGE_LAYOUT_GENERAL
56 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 60 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
57 VkAttachmentDescription& descriptor = descriptors.emplace_back(); 61 descriptors.push_back({
58 descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; 62 .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
59 descriptor.format = format.format; 63 .format = format.format,
60 descriptor.samples = VK_SAMPLE_COUNT_1_BIT; 64 .samples = VK_SAMPLE_COUNT_1_BIT,
61 descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 65 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
62 descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 66 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
63 descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 67 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
64 descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 68 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
65 descriptor.initialLayout = color_layout; 69 .initialLayout = color_layout,
66 descriptor.finalLayout = color_layout; 70 .finalLayout = color_layout,
67 71 });
68 VkAttachmentReference& reference = color_references.emplace_back(); 72
69 reference.attachment = static_cast<u32>(rt); 73 color_references.push_back({
70 reference.layout = color_layout; 74 .attachment = static_cast<u32>(rt),
75 .layout = color_layout,
76 });
71 } 77 }
72 78
73 VkAttachmentReference zeta_attachment_ref; 79 VkAttachmentReference zeta_attachment_ref;
@@ -82,32 +88,36 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
82 const VkImageLayout zeta_layout = params.zeta_texception != 0 88 const VkImageLayout zeta_layout = params.zeta_texception != 0
83 ? VK_IMAGE_LAYOUT_GENERAL 89 ? VK_IMAGE_LAYOUT_GENERAL
84 : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 90 : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
85 VkAttachmentDescription& descriptor = descriptors.emplace_back(); 91 descriptors.push_back({
86 descriptor.flags = 0; 92 .flags = 0,
87 descriptor.format = format.format; 93 .format = format.format,
88 descriptor.samples = VK_SAMPLE_COUNT_1_BIT; 94 .samples = VK_SAMPLE_COUNT_1_BIT,
89 descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 95 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
90 descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 96 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
91 descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 97 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
92 descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 98 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
93 descriptor.initialLayout = zeta_layout; 99 .initialLayout = zeta_layout,
94 descriptor.finalLayout = zeta_layout; 100 .finalLayout = zeta_layout,
95 101 });
96 zeta_attachment_ref.attachment = static_cast<u32>(num_attachments); 102
97 zeta_attachment_ref.layout = zeta_layout; 103 zeta_attachment_ref = {
104 .attachment = static_cast<u32>(num_attachments),
105 .layout = zeta_layout,
106 };
98 } 107 }
99 108
100 VkSubpassDescription subpass_description; 109 const VkSubpassDescription subpass_description{
101 subpass_description.flags = 0; 110 .flags = 0,
102 subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 111 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
103 subpass_description.inputAttachmentCount = 0; 112 .inputAttachmentCount = 0,
104 subpass_description.pInputAttachments = nullptr; 113 .pInputAttachments = nullptr,
105 subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size()); 114 .colorAttachmentCount = static_cast<u32>(color_references.size()),
106 subpass_description.pColorAttachments = color_references.data(); 115 .pColorAttachments = color_references.data(),
107 subpass_description.pResolveAttachments = nullptr; 116 .pResolveAttachments = nullptr,
108 subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr; 117 .pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr,
109 subpass_description.preserveAttachmentCount = 0; 118 .preserveAttachmentCount = 0,
110 subpass_description.pPreserveAttachments = nullptr; 119 .pPreserveAttachments = nullptr,
120 };
111 121
112 VkAccessFlags access = 0; 122 VkAccessFlags access = 0;
113 VkPipelineStageFlags stage = 0; 123 VkPipelineStageFlags stage = 0;
@@ -122,26 +132,27 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
122 stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; 132 stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
123 } 133 }
124 134
125 VkSubpassDependency subpass_dependency; 135 const VkSubpassDependency subpass_dependency{
126 subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 136 .srcSubpass = VK_SUBPASS_EXTERNAL,
127 subpass_dependency.dstSubpass = 0; 137 .dstSubpass = 0,
128 subpass_dependency.srcStageMask = stage; 138 .srcStageMask = stage,
129 subpass_dependency.dstStageMask = stage; 139 .dstStageMask = stage,
130 subpass_dependency.srcAccessMask = 0; 140 .srcAccessMask = 0,
131 subpass_dependency.dstAccessMask = access; 141 .dstAccessMask = access,
132 subpass_dependency.dependencyFlags = 0; 142 .dependencyFlags = 0,
133 143 };
134 VkRenderPassCreateInfo ci; 144
135 ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 145 return device.GetLogical().CreateRenderPass({
136 ci.pNext = nullptr; 146 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
137 ci.flags = 0; 147 .pNext = nullptr,
138 ci.attachmentCount = static_cast<u32>(descriptors.size()); 148 .flags = 0,
139 ci.pAttachments = descriptors.data(); 149 .attachmentCount = static_cast<u32>(descriptors.size()),
140 ci.subpassCount = 1; 150 .pAttachments = descriptors.data(),
141 ci.pSubpasses = &subpass_description; 151 .subpassCount = 1,
142 ci.dependencyCount = 1; 152 .pSubpasses = &subpass_description,
143 ci.pDependencies = &subpass_dependency; 153 .dependencyCount = 1,
144 return device.GetLogical().CreateRenderPass(ci); 154 .pDependencies = &subpass_dependency,
155 });
145} 156}
146 157
147} // namespace Vulkan 158} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
index dc06f545a..f19330a36 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -18,33 +18,32 @@ namespace {
18constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000; 18constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000;
19constexpr std::size_t FENCES_GROW_STEP = 0x40; 19constexpr std::size_t FENCES_GROW_STEP = 0x40;
20 20
21VkFenceCreateInfo BuildFenceCreateInfo() { 21constexpr VkFenceCreateInfo BuildFenceCreateInfo() {
22 VkFenceCreateInfo fence_ci; 22 return {
23 fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 23 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
24 fence_ci.pNext = nullptr; 24 .pNext = nullptr,
25 fence_ci.flags = 0; 25 .flags = 0,
26 return fence_ci; 26 };
27} 27}
28 28
29} // Anonymous namespace 29} // Anonymous namespace
30 30
31class CommandBufferPool final : public VKFencedPool { 31class CommandBufferPool final : public VKFencedPool {
32public: 32public:
33 CommandBufferPool(const VKDevice& device) 33 explicit CommandBufferPool(const VKDevice& device)
34 : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {} 34 : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {}
35 35
36 void Allocate(std::size_t begin, std::size_t end) override { 36 void Allocate(std::size_t begin, std::size_t end) override {
37 // Command buffers are going to be commited, recorded, executed every single usage cycle. 37 // Command buffers are going to be commited, recorded, executed every single usage cycle.
38 // They are also going to be reseted when commited. 38 // They are also going to be reseted when commited.
39 VkCommandPoolCreateInfo command_pool_ci;
40 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
41 command_pool_ci.pNext = nullptr;
42 command_pool_ci.flags =
43 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
44 command_pool_ci.queueFamilyIndex = device.GetGraphicsFamily();
45
46 Pool& pool = pools.emplace_back(); 39 Pool& pool = pools.emplace_back();
47 pool.handle = device.GetLogical().CreateCommandPool(command_pool_ci); 40 pool.handle = device.GetLogical().CreateCommandPool({
41 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
42 .pNext = nullptr,
43 .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
44 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
45 .queueFamilyIndex = device.GetGraphicsFamily(),
46 });
48 pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE); 47 pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE);
49 } 48 }
50 49
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
index 616eacc36..2d5460776 100644
--- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
@@ -44,32 +44,35 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c
44 const bool arbitrary_borders = device.IsExtCustomBorderColorSupported(); 44 const bool arbitrary_borders = device.IsExtCustomBorderColorSupported();
45 const std::array color = tsc.GetBorderColor(); 45 const std::array color = tsc.GetBorderColor();
46 46
47 VkSamplerCustomBorderColorCreateInfoEXT border; 47 VkSamplerCustomBorderColorCreateInfoEXT border{
48 border.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; 48 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
49 border.pNext = nullptr; 49 .pNext = nullptr,
50 border.format = VK_FORMAT_UNDEFINED; 50 .format = VK_FORMAT_UNDEFINED,
51 };
51 std::memcpy(&border.customBorderColor, color.data(), sizeof(color)); 52 std::memcpy(&border.customBorderColor, color.data(), sizeof(color));
52 53
53 VkSamplerCreateInfo ci; 54 return device.GetLogical().CreateSampler({
54 ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 55 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
55 ci.pNext = arbitrary_borders ? &border : nullptr; 56 .pNext = arbitrary_borders ? &border : nullptr,
56 ci.flags = 0; 57 .flags = 0,
57 ci.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter); 58 .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
58 ci.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter); 59 .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
59 ci.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter); 60 .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
60 ci.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter); 61 .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
61 ci.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter); 62 .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
62 ci.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter); 63 .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
63 ci.mipLodBias = tsc.GetLodBias(); 64 .mipLodBias = tsc.GetLodBias(),
64 ci.anisotropyEnable = tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE; 65 .anisotropyEnable =
65 ci.maxAnisotropy = tsc.GetMaxAnisotropy(); 66 static_cast<VkBool32>(tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE),
66 ci.compareEnable = tsc.depth_compare_enabled; 67 .maxAnisotropy = tsc.GetMaxAnisotropy(),
67 ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); 68 .compareEnable = tsc.depth_compare_enabled,
68 ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(); 69 .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
69 ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(); 70 .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(),
70 ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); 71 .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(),
71 ci.unnormalizedCoordinates = VK_FALSE; 72 .borderColor =
72 return device.GetLogical().CreateSampler(ci); 73 arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color),
74 .unnormalizedCoordinates = VK_FALSE,
75 });
73} 76}
74 77
75VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const { 78VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const {
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index 56524e6f3..dbbd0961a 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -100,16 +100,19 @@ void VKScheduler::RequestRenderpass(VkRenderPass renderpass, VkFramebuffer frame
100 state.framebuffer = framebuffer; 100 state.framebuffer = framebuffer;
101 state.render_area = render_area; 101 state.render_area = render_area;
102 102
103 VkRenderPassBeginInfo renderpass_bi; 103 const VkRenderPassBeginInfo renderpass_bi{
104 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 104 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
105 renderpass_bi.pNext = nullptr; 105 .pNext = nullptr,
106 renderpass_bi.renderPass = renderpass; 106 .renderPass = renderpass,
107 renderpass_bi.framebuffer = framebuffer; 107 .framebuffer = framebuffer,
108 renderpass_bi.renderArea.offset.x = 0; 108 .renderArea =
109 renderpass_bi.renderArea.offset.y = 0; 109 {
110 renderpass_bi.renderArea.extent = render_area; 110 .offset = {.x = 0, .y = 0},
111 renderpass_bi.clearValueCount = 0; 111 .extent = render_area,
112 renderpass_bi.pClearValues = nullptr; 112 },
113 .clearValueCount = 0,
114 .pClearValues = nullptr,
115 };
113 116
114 Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) { 117 Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) {
115 if (end_renderpass) { 118 if (end_renderpass) {
@@ -157,16 +160,17 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
157 160
158 current_cmdbuf.End(); 161 current_cmdbuf.End();
159 162
160 VkSubmitInfo submit_info; 163 const VkSubmitInfo submit_info{
161 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 164 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
162 submit_info.pNext = nullptr; 165 .pNext = nullptr,
163 submit_info.waitSemaphoreCount = 0; 166 .waitSemaphoreCount = 0,
164 submit_info.pWaitSemaphores = nullptr; 167 .pWaitSemaphores = nullptr,
165 submit_info.pWaitDstStageMask = nullptr; 168 .pWaitDstStageMask = nullptr,
166 submit_info.commandBufferCount = 1; 169 .commandBufferCount = 1,
167 submit_info.pCommandBuffers = current_cmdbuf.address(); 170 .pCommandBuffers = current_cmdbuf.address(),
168 submit_info.signalSemaphoreCount = semaphore ? 1 : 0; 171 .signalSemaphoreCount = semaphore ? 1U : 0U,
169 submit_info.pSignalSemaphores = &semaphore; 172 .pSignalSemaphores = &semaphore,
173 };
170 switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) { 174 switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) {
171 case VK_SUCCESS: 175 case VK_SUCCESS:
172 break; 176 break;
@@ -181,19 +185,18 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
181void VKScheduler::AllocateNewContext() { 185void VKScheduler::AllocateNewContext() {
182 ++ticks; 186 ++ticks;
183 187
184 VkCommandBufferBeginInfo cmdbuf_bi;
185 cmdbuf_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
186 cmdbuf_bi.pNext = nullptr;
187 cmdbuf_bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
188 cmdbuf_bi.pInheritanceInfo = nullptr;
189
190 std::unique_lock lock{mutex}; 188 std::unique_lock lock{mutex};
191 current_fence = next_fence; 189 current_fence = next_fence;
192 next_fence = &resource_manager.CommitFence(); 190 next_fence = &resource_manager.CommitFence();
193 191
194 current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence), 192 current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence),
195 device.GetDispatchLoader()); 193 device.GetDispatchLoader());
196 current_cmdbuf.Begin(cmdbuf_bi); 194 current_cmdbuf.Begin({
195 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
196 .pNext = nullptr,
197 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
198 .pInheritanceInfo = nullptr,
199 });
197 200
198 // Enable counters once again. These are disabled when a command buffer is finished. 201 // Enable counters once again. These are disabled when a command buffer is finished.
199 if (query_cache) { 202 if (query_cache) {
diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp
index 112df9c71..c1a218d76 100644
--- a/src/video_core/renderer_vulkan/vk_shader_util.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp
@@ -19,13 +19,13 @@ vk::ShaderModule BuildShader(const VKDevice& device, std::size_t code_size, cons
19 const auto data = std::make_unique<u32[]>(code_size / sizeof(u32)); 19 const auto data = std::make_unique<u32[]>(code_size / sizeof(u32));
20 std::memcpy(data.get(), code_data, code_size); 20 std::memcpy(data.get(), code_data, code_size);
21 21
22 VkShaderModuleCreateInfo ci; 22 return device.GetLogical().CreateShaderModule({
23 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 23 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
24 ci.pNext = nullptr; 24 .pNext = nullptr,
25 ci.flags = 0; 25 .flags = 0,
26 ci.codeSize = code_size; 26 .codeSize = code_size,
27 ci.pCode = data.get(); 27 .pCode = data.get(),
28 return device.GetLogical().CreateShaderModule(ci); 28 });
29} 29}
30 30
31} // namespace Vulkan 31} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 45c180221..5eca0ab91 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -71,20 +71,19 @@ VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_
71VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) { 71VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) {
72 const u32 log2 = Common::Log2Ceil64(size); 72 const u32 log2 = Common::Log2Ceil64(size);
73 73
74 VkBufferCreateInfo ci;
75 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
76 ci.pNext = nullptr;
77 ci.flags = 0;
78 ci.size = 1ULL << log2;
79 ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
80 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
81 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
82 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
83 ci.queueFamilyIndexCount = 0;
84 ci.pQueueFamilyIndices = nullptr;
85
86 auto buffer = std::make_unique<VKBuffer>(); 74 auto buffer = std::make_unique<VKBuffer>();
87 buffer->handle = device.GetLogical().CreateBuffer(ci); 75 buffer->handle = device.GetLogical().CreateBuffer({
76 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
77 .pNext = nullptr,
78 .flags = 0,
79 .size = 1ULL << log2,
80 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
81 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
82 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
83 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
84 .queueFamilyIndexCount = 0,
85 .pQueueFamilyIndices = nullptr,
86 });
88 buffer->commit = memory_manager.Commit(buffer->handle, host_visible); 87 buffer->commit = memory_manager.Commit(buffer->handle, host_visible);
89 88
90 auto& entries = GetCache(host_visible)[log2].entries; 89 auto& entries = GetCache(host_visible)[log2].entries;
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index e5a583dd5..9151d9fb1 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -158,6 +158,7 @@ void StateTracker::Initialize() {
158 SetupDirtyFrontFace(tables); 158 SetupDirtyFrontFace(tables);
159 SetupDirtyPrimitiveTopology(tables); 159 SetupDirtyPrimitiveTopology(tables);
160 SetupDirtyStencilOp(tables); 160 SetupDirtyStencilOp(tables);
161 SetupDirtyStencilTestEnable(tables);
161} 162}
162 163
163void StateTracker::InvalidateCommandBufferState() { 164void StateTracker::InvalidateCommandBufferState() {
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
index 2d28a6c47..a5526a3f5 100644
--- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
+++ b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
@@ -122,30 +122,27 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) {
122 // Substract from the preferred heap size some bytes to avoid getting out of memory. 122 // Substract from the preferred heap size some bytes to avoid getting out of memory.
123 const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size; 123 const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
124 const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024; 124 const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024;
125 125 buffer = device.GetLogical().CreateBuffer({
126 VkBufferCreateInfo buffer_ci; 126 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
127 buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 127 .pNext = nullptr,
128 buffer_ci.pNext = nullptr; 128 .flags = 0,
129 buffer_ci.flags = 0; 129 .size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size),
130 buffer_ci.size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size); 130 .usage = usage,
131 buffer_ci.usage = usage; 131 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
132 buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 132 .queueFamilyIndexCount = 0,
133 buffer_ci.queueFamilyIndexCount = 0; 133 .pQueueFamilyIndices = nullptr,
134 buffer_ci.pQueueFamilyIndices = nullptr; 134 });
135
136 buffer = device.GetLogical().CreateBuffer(buffer_ci);
137 135
138 const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer); 136 const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer);
139 const u32 required_flags = requirements.memoryTypeBits; 137 const u32 required_flags = requirements.memoryTypeBits;
140 stream_buffer_size = static_cast<u64>(requirements.size); 138 stream_buffer_size = static_cast<u64>(requirements.size);
141 139
142 VkMemoryAllocateInfo memory_ai; 140 memory = device.GetLogical().AllocateMemory({
143 memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 141 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
144 memory_ai.pNext = nullptr; 142 .pNext = nullptr,
145 memory_ai.allocationSize = requirements.size; 143 .allocationSize = requirements.size,
146 memory_ai.memoryTypeIndex = GetMemoryType(memory_properties, required_flags); 144 .memoryTypeIndex = GetMemoryType(memory_properties, required_flags),
147 145 });
148 memory = device.GetLogical().AllocateMemory(memory_ai);
149 buffer.BindMemory(*memory, 0); 146 buffer.BindMemory(*memory, 0);
150} 147}
151 148
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index bffd8f32a..c25e312b6 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -95,15 +95,16 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore, VKFence& fence) {
95 const auto present_queue{device.GetPresentQueue()}; 95 const auto present_queue{device.GetPresentQueue()};
96 bool recreated = false; 96 bool recreated = false;
97 97
98 VkPresentInfoKHR present_info; 98 const VkPresentInfoKHR present_info{
99 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 99 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
100 present_info.pNext = nullptr; 100 .pNext = nullptr,
101 present_info.waitSemaphoreCount = render_semaphore ? 2U : 1U; 101 .waitSemaphoreCount = render_semaphore ? 2U : 1U,
102 present_info.pWaitSemaphores = semaphores.data(); 102 .pWaitSemaphores = semaphores.data(),
103 present_info.swapchainCount = 1; 103 .swapchainCount = 1,
104 present_info.pSwapchains = swapchain.address(); 104 .pSwapchains = swapchain.address(),
105 present_info.pImageIndices = &image_index; 105 .pImageIndices = &image_index,
106 present_info.pResults = nullptr; 106 .pResults = nullptr,
107 };
107 108
108 switch (const VkResult result = present_queue.Present(present_info)) { 109 switch (const VkResult result = present_queue.Present(present_info)) {
109 case VK_SUCCESS: 110 case VK_SUCCESS:
@@ -147,24 +148,25 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
147 requested_image_count = capabilities.maxImageCount; 148 requested_image_count = capabilities.maxImageCount;
148 } 149 }
149 150
150 VkSwapchainCreateInfoKHR swapchain_ci; 151 VkSwapchainCreateInfoKHR swapchain_ci{
151 swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 152 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
152 swapchain_ci.pNext = nullptr; 153 .pNext = nullptr,
153 swapchain_ci.flags = 0; 154 .flags = 0,
154 swapchain_ci.surface = surface; 155 .surface = surface,
155 swapchain_ci.minImageCount = requested_image_count; 156 .minImageCount = requested_image_count,
156 swapchain_ci.imageFormat = surface_format.format; 157 .imageFormat = surface_format.format,
157 swapchain_ci.imageColorSpace = surface_format.colorSpace; 158 .imageColorSpace = surface_format.colorSpace,
158 swapchain_ci.imageArrayLayers = 1; 159 .imageArrayLayers = 1,
159 swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 160 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
160 swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 161 .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
161 swapchain_ci.queueFamilyIndexCount = 0; 162 .queueFamilyIndexCount = 0,
162 swapchain_ci.pQueueFamilyIndices = nullptr; 163 .pQueueFamilyIndices = nullptr,
163 swapchain_ci.preTransform = capabilities.currentTransform; 164 .preTransform = capabilities.currentTransform,
164 swapchain_ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 165 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
165 swapchain_ci.presentMode = present_mode; 166 .presentMode = present_mode,
166 swapchain_ci.clipped = VK_FALSE; 167 .clipped = VK_FALSE,
167 swapchain_ci.oldSwapchain = nullptr; 168 .oldSwapchain = nullptr,
169 };
168 170
169 const u32 graphics_family{device.GetGraphicsFamily()}; 171 const u32 graphics_family{device.GetGraphicsFamily()};
170 const u32 present_family{device.GetPresentFamily()}; 172 const u32 present_family{device.GetPresentFamily()};
@@ -173,8 +175,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
173 swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT; 175 swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
174 swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size()); 176 swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size());
175 swapchain_ci.pQueueFamilyIndices = queue_indices.data(); 177 swapchain_ci.pQueueFamilyIndices = queue_indices.data();
176 } else {
177 swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
178 } 178 }
179 179
180 // Request the size again to reduce the possibility of a TOCTOU race condition. 180 // Request the size again to reduce the possibility of a TOCTOU race condition.
@@ -200,20 +200,28 @@ void VKSwapchain::CreateSemaphores() {
200} 200}
201 201
202void VKSwapchain::CreateImageViews() { 202void VKSwapchain::CreateImageViews() {
203 VkImageViewCreateInfo ci; 203 VkImageViewCreateInfo ci{
204 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 204 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
205 ci.pNext = nullptr; 205 .pNext = nullptr,
206 ci.flags = 0; 206 .flags = 0,
207 // ci.image 207 .viewType = VK_IMAGE_VIEW_TYPE_2D,
208 ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 208 .format = image_format,
209 ci.format = image_format; 209 .components =
210 ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 210 {
211 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 211 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
212 ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 212 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
213 ci.subresourceRange.baseMipLevel = 0; 213 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
214 ci.subresourceRange.levelCount = 1; 214 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
215 ci.subresourceRange.baseArrayLayer = 0; 215 },
216 ci.subresourceRange.layerCount = 1; 216 .subresourceRange =
217 {
218 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
219 .baseMipLevel = 0,
220 .levelCount = 1,
221 .baseArrayLayer = 0,
222 .layerCount = 1,
223 },
224 };
217 225
218 image_views.resize(image_count); 226 image_views.resize(image_count);
219 for (std::size_t i = 0; i < image_count; i++) { 227 for (std::size_t i = 0; i < image_count; i++) {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 430031665..9bc18c21a 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -95,17 +95,18 @@ VkImageViewType GetImageViewType(SurfaceTarget target) {
95vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params, 95vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params,
96 std::size_t host_memory_size) { 96 std::size_t host_memory_size) {
97 // TODO(Rodrigo): Move texture buffer creation to the buffer cache 97 // TODO(Rodrigo): Move texture buffer creation to the buffer cache
98 VkBufferCreateInfo ci; 98 return device.GetLogical().CreateBuffer({
99 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 99 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
100 ci.pNext = nullptr; 100 .pNext = nullptr,
101 ci.flags = 0; 101 .flags = 0,
102 ci.size = static_cast<VkDeviceSize>(host_memory_size); 102 .size = static_cast<VkDeviceSize>(host_memory_size),
103 ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | 103 .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
104 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 104 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
105 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 105 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
106 ci.queueFamilyIndexCount = 0; 106 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
107 ci.pQueueFamilyIndices = nullptr; 107 .queueFamilyIndexCount = 0,
108 return device.GetLogical().CreateBuffer(ci); 108 .pQueueFamilyIndices = nullptr,
109 });
109} 110}
110 111
111VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device, 112VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
@@ -113,15 +114,16 @@ VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
113 std::size_t host_memory_size) { 114 std::size_t host_memory_size) {
114 ASSERT(params.IsBuffer()); 115 ASSERT(params.IsBuffer());
115 116
116 VkBufferViewCreateInfo ci; 117 return {
117 ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; 118 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
118 ci.pNext = nullptr; 119 .pNext = nullptr,
119 ci.flags = 0; 120 .flags = 0,
120 ci.buffer = buffer; 121 .buffer = buffer,
121 ci.format = MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format; 122 .format =
122 ci.offset = 0; 123 MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format,
123 ci.range = static_cast<VkDeviceSize>(host_memory_size); 124 .offset = 0,
124 return ci; 125 .range = static_cast<VkDeviceSize>(host_memory_size),
126 };
125} 127}
126 128
127VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) { 129VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) {
@@ -130,23 +132,23 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP
130 const auto [format, attachable, storage] = 132 const auto [format, attachable, storage] =
131 MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format); 133 MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format);
132 134
133 VkImageCreateInfo ci; 135 VkImageCreateInfo ci{
134 ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 136 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
135 ci.pNext = nullptr; 137 .pNext = nullptr,
136 ci.flags = 0; 138 .flags = 0,
137 ci.imageType = SurfaceTargetToImage(params.target); 139 .imageType = SurfaceTargetToImage(params.target),
138 ci.format = format; 140 .format = format,
139 ci.mipLevels = params.num_levels; 141 .mipLevels = params.num_levels,
140 ci.arrayLayers = static_cast<u32>(params.GetNumLayers()); 142 .arrayLayers = static_cast<u32>(params.GetNumLayers()),
141 ci.samples = VK_SAMPLE_COUNT_1_BIT; 143 .samples = VK_SAMPLE_COUNT_1_BIT,
142 ci.tiling = VK_IMAGE_TILING_OPTIMAL; 144 .tiling = VK_IMAGE_TILING_OPTIMAL,
143 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 145 .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
144 ci.queueFamilyIndexCount = 0; 146 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
145 ci.pQueueFamilyIndices = nullptr; 147 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
146 ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 148 .queueFamilyIndexCount = 0,
147 149 .pQueueFamilyIndices = nullptr,
148 ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | 150 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
149 VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 151 };
150 if (attachable) { 152 if (attachable) {
151 ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT 153 ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
152 : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 154 : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -281,12 +283,10 @@ void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) {
281 VkBufferMemoryBarrier barrier; 283 VkBufferMemoryBarrier barrier;
282 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 284 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
283 barrier.pNext = nullptr; 285 barrier.pNext = nullptr;
284 barrier.srcAccessMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 286 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
285 barrier.dstAccessMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; 287 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
286 barrier.srcQueueFamilyIndex = VK_ACCESS_TRANSFER_WRITE_BIT; 288 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // They'll be ignored anyway
287 barrier.dstQueueFamilyIndex = VK_ACCESS_SHADER_READ_BIT; 289 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
288 barrier.srcQueueFamilyIndex = 0;
289 barrier.dstQueueFamilyIndex = 0;
290 barrier.buffer = dst_buffer; 290 barrier.buffer = dst_buffer;
291 barrier.offset = 0; 291 barrier.offset = 0;
292 barrier.size = size; 292 barrier.size = size;
@@ -323,22 +323,25 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) {
323} 323}
324 324
325VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const { 325VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const {
326 VkBufferImageCopy copy; 326 return {
327 copy.bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted); 327 .bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted),
328 copy.bufferRowLength = 0; 328 .bufferRowLength = 0,
329 copy.bufferImageHeight = 0; 329 .bufferImageHeight = 0,
330 copy.imageSubresource.aspectMask = image->GetAspectMask(); 330 .imageSubresource =
331 copy.imageSubresource.mipLevel = level; 331 {
332 copy.imageSubresource.baseArrayLayer = 0; 332 .aspectMask = image->GetAspectMask(),
333 copy.imageSubresource.layerCount = static_cast<u32>(params.GetNumLayers()); 333 .mipLevel = level,
334 copy.imageOffset.x = 0; 334 .baseArrayLayer = 0,
335 copy.imageOffset.y = 0; 335 .layerCount = static_cast<u32>(params.GetNumLayers()),
336 copy.imageOffset.z = 0; 336 },
337 copy.imageExtent.width = params.GetMipWidth(level); 337 .imageOffset = {.x = 0, .y = 0, .z = 0},
338 copy.imageExtent.height = params.GetMipHeight(level); 338 .imageExtent =
339 copy.imageExtent.depth = 339 {
340 params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1; 340 .width = params.GetMipWidth(level),
341 return copy; 341 .height = params.GetMipHeight(level),
342 .depth = params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1U,
343 },
344 };
342} 345}
343 346
344VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { 347VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const {
@@ -418,20 +421,29 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
418 ASSERT(num_slices == params.depth); 421 ASSERT(num_slices == params.depth);
419 } 422 }
420 423
421 VkImageViewCreateInfo ci; 424 image_view = device.GetLogical().CreateImageView({
422 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 425 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
423 ci.pNext = nullptr; 426 .pNext = nullptr,
424 ci.flags = 0; 427 .flags = 0,
425 ci.image = surface.GetImageHandle(); 428 .image = surface.GetImageHandle(),
426 ci.viewType = image_view_type; 429 .viewType = image_view_type,
427 ci.format = surface.GetImage().GetFormat(); 430 .format = surface.GetImage().GetFormat(),
428 ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]}; 431 .components =
429 ci.subresourceRange.aspectMask = aspect; 432 {
430 ci.subresourceRange.baseMipLevel = base_level; 433 .r = swizzle[0],
431 ci.subresourceRange.levelCount = num_levels; 434 .g = swizzle[1],
432 ci.subresourceRange.baseArrayLayer = base_layer; 435 .b = swizzle[2],
433 ci.subresourceRange.layerCount = num_layers; 436 .a = swizzle[3],
434 image_view = device.GetLogical().CreateImageView(ci); 437 },
438 .subresourceRange =
439 {
440 .aspectMask = aspect,
441 .baseMipLevel = base_level,
442 .levelCount = num_levels,
443 .baseArrayLayer = base_layer,
444 .layerCount = num_layers,
445 },
446 });
435 447
436 return last_image_view = *image_view; 448 return last_image_view = *image_view;
437} 449}
@@ -441,17 +453,26 @@ VkImageView CachedSurfaceView::GetAttachment() {
441 return *render_target; 453 return *render_target;
442 } 454 }
443 455
444 VkImageViewCreateInfo ci; 456 VkImageViewCreateInfo ci{
445 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 457 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
446 ci.pNext = nullptr; 458 .pNext = nullptr,
447 ci.flags = 0; 459 .flags = 0,
448 ci.image = surface.GetImageHandle(); 460 .image = surface.GetImageHandle(),
449 ci.format = surface.GetImage().GetFormat(); 461 .format = surface.GetImage().GetFormat(),
450 ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 462 .components =
451 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 463 {
452 ci.subresourceRange.aspectMask = aspect_mask; 464 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
453 ci.subresourceRange.baseMipLevel = base_level; 465 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
454 ci.subresourceRange.levelCount = num_levels; 466 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
467 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
468 },
469 .subresourceRange =
470 {
471 .aspectMask = aspect_mask,
472 .baseMipLevel = base_level,
473 .levelCount = num_levels,
474 },
475 };
455 if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { 476 if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) {
456 ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; 477 ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
457 ci.subresourceRange.baseArrayLayer = base_slice; 478 ci.subresourceRange.baseArrayLayer = base_slice;
@@ -504,24 +525,40 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface,
504 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 525 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
505 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 526 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
506 527
507 VkImageCopy copy; 528 const VkImageCopy copy{
508 copy.srcSubresource.aspectMask = src_surface->GetAspectMask(); 529 .srcSubresource =
509 copy.srcSubresource.mipLevel = copy_params.source_level; 530 {
510 copy.srcSubresource.baseArrayLayer = copy_params.source_z; 531 .aspectMask = src_surface->GetAspectMask(),
511 copy.srcSubresource.layerCount = num_layers; 532 .mipLevel = copy_params.source_level,
512 copy.srcOffset.x = copy_params.source_x; 533 .baseArrayLayer = copy_params.source_z,
513 copy.srcOffset.y = copy_params.source_y; 534 .layerCount = num_layers,
514 copy.srcOffset.z = 0; 535 },
515 copy.dstSubresource.aspectMask = dst_surface->GetAspectMask(); 536 .srcOffset =
516 copy.dstSubresource.mipLevel = copy_params.dest_level; 537 {
517 copy.dstSubresource.baseArrayLayer = dst_base_layer; 538 .x = static_cast<s32>(copy_params.source_x),
518 copy.dstSubresource.layerCount = num_layers; 539 .y = static_cast<s32>(copy_params.source_y),
519 copy.dstOffset.x = copy_params.dest_x; 540 .z = 0,
520 copy.dstOffset.y = copy_params.dest_y; 541 },
521 copy.dstOffset.z = dst_offset_z; 542 .dstSubresource =
522 copy.extent.width = copy_params.width; 543 {
523 copy.extent.height = copy_params.height; 544 .aspectMask = dst_surface->GetAspectMask(),
524 copy.extent.depth = extent_z; 545 .mipLevel = copy_params.dest_level,
546 .baseArrayLayer = dst_base_layer,
547 .layerCount = num_layers,
548 },
549 .dstOffset =
550 {
551 .x = static_cast<s32>(copy_params.dest_x),
552 .y = static_cast<s32>(copy_params.dest_y),
553 .z = static_cast<s32>(dst_offset_z),
554 },
555 .extent =
556 {
557 .width = copy_params.width,
558 .height = copy_params.height,
559 .depth = extent_z,
560 },
561 };
525 562
526 const VkImage src_image = src_surface->GetImageHandle(); 563 const VkImage src_image = src_surface->GetImageHandle();
527 const VkImage dst_image = dst_surface->GetImageHandle(); 564 const VkImage dst_image = dst_surface->GetImageHandle();
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 051298cc8..14cac38ea 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -377,24 +377,26 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
377 377
378Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions, 378Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
379 InstanceDispatch& dld) noexcept { 379 InstanceDispatch& dld) noexcept {
380 VkApplicationInfo application_info; 380 static constexpr VkApplicationInfo application_info{
381 application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 381 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
382 application_info.pNext = nullptr; 382 .pNext = nullptr,
383 application_info.pApplicationName = "yuzu Emulator"; 383 .pApplicationName = "yuzu Emulator",
384 application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0); 384 .applicationVersion = VK_MAKE_VERSION(0, 1, 0),
385 application_info.pEngineName = "yuzu Emulator"; 385 .pEngineName = "yuzu Emulator",
386 application_info.engineVersion = VK_MAKE_VERSION(0, 1, 0); 386 .engineVersion = VK_MAKE_VERSION(0, 1, 0),
387 application_info.apiVersion = VK_API_VERSION_1_1; 387 .apiVersion = VK_API_VERSION_1_1,
388 388 };
389 VkInstanceCreateInfo ci; 389
390 ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 390 const VkInstanceCreateInfo ci{
391 ci.pNext = nullptr; 391 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
392 ci.flags = 0; 392 .pNext = nullptr,
393 ci.pApplicationInfo = &application_info; 393 .flags = 0,
394 ci.enabledLayerCount = layers.size(); 394 .pApplicationInfo = &application_info,
395 ci.ppEnabledLayerNames = layers.data(); 395 .enabledLayerCount = layers.size(),
396 ci.enabledExtensionCount = extensions.size(); 396 .ppEnabledLayerNames = layers.data(),
397 ci.ppEnabledExtensionNames = extensions.data(); 397 .enabledExtensionCount = extensions.size(),
398 .ppEnabledExtensionNames = extensions.data(),
399 };
398 400
399 VkInstance instance; 401 VkInstance instance;
400 if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) { 402 if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) {
@@ -425,19 +427,20 @@ std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices(
425 427
426DebugCallback Instance::TryCreateDebugCallback( 428DebugCallback Instance::TryCreateDebugCallback(
427 PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept { 429 PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept {
428 VkDebugUtilsMessengerCreateInfoEXT ci; 430 const VkDebugUtilsMessengerCreateInfoEXT ci{
429 ci.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; 431 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
430 ci.pNext = nullptr; 432 .pNext = nullptr,
431 ci.flags = 0; 433 .flags = 0,
432 ci.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | 434 .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
433 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | 435 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
434 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | 436 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
435 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; 437 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
436 ci.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | 438 .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
437 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | 439 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
438 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; 440 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
439 ci.pfnUserCallback = callback; 441 .pfnUserCallback = callback,
440 ci.pUserData = nullptr; 442 .pUserData = nullptr,
443 };
441 444
442 VkDebugUtilsMessengerEXT messenger; 445 VkDebugUtilsMessengerEXT messenger;
443 if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) { 446 if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) {
@@ -468,12 +471,13 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c
468} 471}
469 472
470CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const { 473CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const {
471 VkCommandBufferAllocateInfo ai; 474 const VkCommandBufferAllocateInfo ai{
472 ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 475 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
473 ai.pNext = nullptr; 476 .pNext = nullptr,
474 ai.commandPool = handle; 477 .commandPool = handle,
475 ai.level = level; 478 .level = level,
476 ai.commandBufferCount = static_cast<u32>(num_buffers); 479 .commandBufferCount = static_cast<u32>(num_buffers),
480 };
477 481
478 std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers); 482 std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers);
479 switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) { 483 switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) {
@@ -497,17 +501,18 @@ std::vector<VkImage> SwapchainKHR::GetImages() const {
497Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci, 501Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
498 Span<const char*> enabled_extensions, const void* next, 502 Span<const char*> enabled_extensions, const void* next,
499 DeviceDispatch& dld) noexcept { 503 DeviceDispatch& dld) noexcept {
500 VkDeviceCreateInfo ci; 504 const VkDeviceCreateInfo ci{
501 ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 505 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
502 ci.pNext = next; 506 .pNext = next,
503 ci.flags = 0; 507 .flags = 0,
504 ci.queueCreateInfoCount = queues_ci.size(); 508 .queueCreateInfoCount = queues_ci.size(),
505 ci.pQueueCreateInfos = queues_ci.data(); 509 .pQueueCreateInfos = queues_ci.data(),
506 ci.enabledLayerCount = 0; 510 .enabledLayerCount = 0,
507 ci.ppEnabledLayerNames = nullptr; 511 .ppEnabledLayerNames = nullptr,
508 ci.enabledExtensionCount = enabled_extensions.size(); 512 .enabledExtensionCount = enabled_extensions.size(),
509 ci.ppEnabledExtensionNames = enabled_extensions.data(); 513 .ppEnabledExtensionNames = enabled_extensions.data(),
510 ci.pEnabledFeatures = nullptr; 514 .pEnabledFeatures = nullptr,
515 };
511 516
512 VkDevice device; 517 VkDevice device;
513 if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) { 518 if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) {
@@ -548,10 +553,11 @@ ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
548} 553}
549 554
550Semaphore Device::CreateSemaphore() const { 555Semaphore Device::CreateSemaphore() const {
551 VkSemaphoreCreateInfo ci; 556 static constexpr VkSemaphoreCreateInfo ci{
552 ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 557 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
553 ci.pNext = nullptr; 558 .pNext = nullptr,
554 ci.flags = 0; 559 .flags = 0,
560 };
555 561
556 VkSemaphore object; 562 VkSemaphore object;
557 Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object)); 563 Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object));
@@ -639,10 +645,12 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons
639} 645}
640 646
641Event Device::CreateEvent() const { 647Event Device::CreateEvent() const {
642 VkEventCreateInfo ci; 648 static constexpr VkEventCreateInfo ci{
643 ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; 649 .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
644 ci.pNext = nullptr; 650 .pNext = nullptr,
645 ci.flags = 0; 651 .flags = 0,
652 };
653
646 VkEvent object; 654 VkEvent object;
647 Check(dld->vkCreateEvent(handle, &ci, nullptr, &object)); 655 Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
648 return Event(object, handle, *dld); 656 return Event(object, handle, *dld);
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp
new file mode 100644
index 000000000..b7f66d7ee
--- /dev/null
+++ b/src/video_core/shader/async_shaders.cpp
@@ -0,0 +1,181 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <chrono>
6#include <condition_variable>
7#include <mutex>
8#include <thread>
9#include <vector>
10#include "video_core/engines/maxwell_3d.h"
11#include "video_core/renderer_base.h"
12#include "video_core/renderer_opengl/gl_shader_cache.h"
13#include "video_core/shader/async_shaders.h"
14
15namespace VideoCommon::Shader {
16
17AsyncShaders::AsyncShaders(Core::Frontend::EmuWindow& emu_window) : emu_window(emu_window) {}
18
19AsyncShaders::~AsyncShaders() {
20 KillWorkers();
21}
22
23void AsyncShaders::AllocateWorkers(std::size_t num_workers) {
24 // If we're already have workers queued or don't want to queue workers, ignore
25 if (num_workers == worker_threads.size() || num_workers == 0) {
26 return;
27 }
28
29 // If workers already exist, clear them
30 if (!worker_threads.empty()) {
31 FreeWorkers();
32 }
33
34 // Create workers
35 for (std::size_t i = 0; i < num_workers; i++) {
36 context_list.push_back(emu_window.CreateSharedContext());
37 worker_threads.push_back(std::move(
38 std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get())));
39 }
40}
41
42void AsyncShaders::FreeWorkers() {
43 // Mark all threads to quit
44 is_thread_exiting.store(true);
45 cv.notify_all();
46 for (auto& thread : worker_threads) {
47 thread.join();
48 }
49 // Clear our shared contexts
50 context_list.clear();
51
52 // Clear our worker threads
53 worker_threads.clear();
54}
55
56void AsyncShaders::KillWorkers() {
57 is_thread_exiting.store(true);
58 for (auto& thread : worker_threads) {
59 thread.detach();
60 }
61 // Clear our shared contexts
62 context_list.clear();
63
64 // Clear our worker threads
65 worker_threads.clear();
66}
67
68bool AsyncShaders::HasWorkQueued() {
69 return !pending_queue.empty();
70}
71
72bool AsyncShaders::HasCompletedWork() {
73 std::shared_lock lock{completed_mutex};
74 return !finished_work.empty();
75}
76
77bool AsyncShaders::IsShaderAsync(const Tegra::GPU& gpu) const {
78 const auto& regs = gpu.Maxwell3D().regs;
79
80 // If something is using depth, we can assume that games are not rendering anything which will
81 // be used one time.
82 if (regs.zeta_enable) {
83 return true;
84 }
85
86 // If games are using a small index count, we can assume these are full screen quads. Usually
87 // these shaders are only used once for building textures so we can assume they can't be built
88 // async
89 if (regs.index_array.count <= 6 || regs.vertex_buffer.count <= 6) {
90 return false;
91 }
92
93 return true;
94}
95
96std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() {
97 std::vector<AsyncShaders::Result> results;
98 {
99 std::unique_lock lock{completed_mutex};
100 results.assign(std::make_move_iterator(finished_work.begin()),
101 std::make_move_iterator(finished_work.end()));
102 finished_work.clear();
103 }
104 return results;
105}
106
107void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device,
108 Tegra::Engines::ShaderType shader_type, u64 uid,
109 std::vector<u64> code, std::vector<u64> code_b,
110 u32 main_offset,
111 VideoCommon::Shader::CompilerSettings compiler_settings,
112 const VideoCommon::Shader::Registry& registry,
113 VAddr cpu_addr) {
114 WorkerParams params{device.UseAssemblyShaders() ? AsyncShaders::Backend::GLASM
115 : AsyncShaders::Backend::OpenGL,
116 device,
117 shader_type,
118 uid,
119 std::move(code),
120 std::move(code_b),
121 main_offset,
122 compiler_settings,
123 registry,
124 cpu_addr};
125 std::unique_lock lock(queue_mutex);
126 pending_queue.push_back(std::move(params));
127 cv.notify_one();
128}
129
130void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context) {
131 using namespace std::chrono_literals;
132 while (!is_thread_exiting.load(std::memory_order_relaxed)) {
133 std::unique_lock lock{queue_mutex};
134 cv.wait(lock, [this] { return HasWorkQueued() || is_thread_exiting; });
135 if (is_thread_exiting) {
136 return;
137 }
138
139 // Partial lock to allow all threads to read at the same time
140 if (!HasWorkQueued()) {
141 continue;
142 }
143 // Another thread beat us, just unlock and wait for the next load
144 if (pending_queue.empty()) {
145 continue;
146 }
147 // Pull work from queue
148 WorkerParams work = std::move(pending_queue.front());
149 pending_queue.pop_front();
150
151 lock.unlock();
152
153 if (work.backend == AsyncShaders::Backend::OpenGL ||
154 work.backend == AsyncShaders::Backend::GLASM) {
155 const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, work.registry);
156 const auto scope = context->Acquire();
157 auto program =
158 OpenGL::BuildShader(work.device, work.shader_type, work.uid, ir, work.registry);
159 Result result{};
160 result.backend = work.backend;
161 result.cpu_address = work.cpu_address;
162 result.uid = work.uid;
163 result.code = std::move(work.code);
164 result.code_b = std::move(work.code_b);
165 result.shader_type = work.shader_type;
166
167 if (work.backend == AsyncShaders::Backend::OpenGL) {
168 result.program.opengl = std::move(program->source_program);
169 } else if (work.backend == AsyncShaders::Backend::GLASM) {
170 result.program.glasm = std::move(program->assembly_program);
171 }
172
173 {
174 std::unique_lock complete_lock(completed_mutex);
175 finished_work.push_back(std::move(result));
176 }
177 }
178 }
179}
180
181} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h
new file mode 100644
index 000000000..2f5ee94ad
--- /dev/null
+++ b/src/video_core/shader/async_shaders.h
@@ -0,0 +1,109 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <condition_variable>
8#include <deque>
9#include <memory>
10#include <shared_mutex>
11#include <thread>
12#include "common/bit_field.h"
13#include "common/common_types.h"
14#include "video_core/renderer_opengl/gl_device.h"
15#include "video_core/renderer_opengl/gl_resource_manager.h"
16#include "video_core/renderer_opengl/gl_shader_decompiler.h"
17
18namespace Core::Frontend {
19class EmuWindow;
20class GraphicsContext;
21} // namespace Core::Frontend
22
23namespace Tegra {
24class GPU;
25}
26
27namespace VideoCommon::Shader {
28
29class AsyncShaders {
30public:
31 enum class Backend {
32 OpenGL,
33 GLASM,
34 };
35
36 struct ResultPrograms {
37 OpenGL::OGLProgram opengl;
38 OpenGL::OGLAssemblyProgram glasm;
39 };
40
41 struct Result {
42 u64 uid;
43 VAddr cpu_address;
44 Backend backend;
45 ResultPrograms program;
46 std::vector<u64> code;
47 std::vector<u64> code_b;
48 Tegra::Engines::ShaderType shader_type;
49 };
50
51 explicit AsyncShaders(Core::Frontend::EmuWindow& emu_window);
52 ~AsyncShaders();
53
54 /// Start up shader worker threads
55 void AllocateWorkers(std::size_t num_workers);
56
57 /// Clear the shader queue and kill all worker threads
58 void FreeWorkers();
59
60 // Force end all threads
61 void KillWorkers();
62
63 /// Check to see if any shaders have actually been compiled
64 bool HasCompletedWork();
65
66 /// Deduce if a shader can be build on another thread of MUST be built in sync. We cannot build
67 /// every shader async as some shaders are only built and executed once. We try to "guess" which
68 /// shader would be used only once
69 bool IsShaderAsync(const Tegra::GPU& gpu) const;
70
71 /// Pulls completed compiled shaders
72 std::vector<Result> GetCompletedWork();
73
74 void QueueOpenGLShader(const OpenGL::Device& device, Tegra::Engines::ShaderType shader_type,
75 u64 uid, std::vector<u64> code, std::vector<u64> code_b, u32 main_offset,
76 VideoCommon::Shader::CompilerSettings compiler_settings,
77 const VideoCommon::Shader::Registry& registry, VAddr cpu_addr);
78
79private:
80 void ShaderCompilerThread(Core::Frontend::GraphicsContext* context);
81
82 /// Check our worker queue to see if we have any work queued already
83 bool HasWorkQueued();
84
85 struct WorkerParams {
86 AsyncShaders::Backend backend;
87 OpenGL::Device device;
88 Tegra::Engines::ShaderType shader_type;
89 u64 uid;
90 std::vector<u64> code;
91 std::vector<u64> code_b;
92 u32 main_offset;
93 VideoCommon::Shader::CompilerSettings compiler_settings;
94 VideoCommon::Shader::Registry registry;
95 VAddr cpu_address;
96 };
97
98 std::condition_variable cv;
99 std::mutex queue_mutex;
100 std::shared_mutex completed_mutex;
101 std::atomic<bool> is_thread_exiting{};
102 std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list;
103 std::vector<std::thread> worker_threads;
104 std::deque<WorkerParams> pending_queue;
105 std::vector<AsyncShaders::Result> finished_work;
106 Core::Frontend::EmuWindow& emu_window;
107};
108
109} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h
index b7608fc7b..015a789d6 100644
--- a/src/video_core/shader_cache.h
+++ b/src/video_core/shader_cache.h
@@ -209,11 +209,11 @@ private:
209 } 209 }
210 210
211 // Remove them from the cache 211 // Remove them from the cache
212 const auto is_removed = [&removed_shaders](std::unique_ptr<T>& shader) { 212 const auto is_removed = [&removed_shaders](const std::unique_ptr<T>& shader) {
213 return std::find(removed_shaders.begin(), removed_shaders.end(), shader.get()) != 213 return std::find(removed_shaders.begin(), removed_shaders.end(), shader.get()) !=
214 removed_shaders.end(); 214 removed_shaders.end();
215 }; 215 };
216 storage.erase(std::remove_if(storage.begin(), storage.end(), is_removed), storage.end()); 216 std::erase_if(storage, is_removed);
217 } 217 }
218 218
219 /// @brief Creates a new entry in the lookup cache and returns its pointer 219 /// @brief Creates a new entry in the lookup cache and returns its pointer
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp
new file mode 100644
index 000000000..c3c71657d
--- /dev/null
+++ b/src/video_core/shader_notify.cpp
@@ -0,0 +1,42 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "video_core/shader_notify.h"
6
7using namespace std::chrono_literals;
8
9namespace VideoCore {
10namespace {
11constexpr auto UPDATE_TICK = 32ms;
12}
13
14ShaderNotify::ShaderNotify() = default;
15ShaderNotify::~ShaderNotify() = default;
16
17std::size_t ShaderNotify::GetShadersBuilding() {
18 const auto now = std::chrono::high_resolution_clock::now();
19 const auto diff = now - last_update;
20 if (diff > UPDATE_TICK) {
21 std::shared_lock lock(mutex);
22 last_updated_count = accurate_count;
23 }
24 return last_updated_count;
25}
26
27std::size_t ShaderNotify::GetShadersBuildingAccurate() {
28 std::shared_lock lock{mutex};
29 return accurate_count;
30}
31
32void ShaderNotify::MarkShaderComplete() {
33 std::unique_lock lock{mutex};
34 accurate_count--;
35}
36
37void ShaderNotify::MarkSharderBuilding() {
38 std::unique_lock lock{mutex};
39 accurate_count++;
40}
41
42} // namespace VideoCore
diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h
new file mode 100644
index 000000000..a9c92d179
--- /dev/null
+++ b/src/video_core/shader_notify.h
@@ -0,0 +1,29 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <chrono>
8#include <shared_mutex>
9#include "common/common_types.h"
10
11namespace VideoCore {
12class ShaderNotify {
13public:
14 ShaderNotify();
15 ~ShaderNotify();
16
17 std::size_t GetShadersBuilding();
18 std::size_t GetShadersBuildingAccurate();
19
20 void MarkShaderComplete();
21 void MarkSharderBuilding();
22
23private:
24 std::size_t last_updated_count{};
25 std::size_t accurate_count{};
26 std::shared_mutex mutex;
27 std::chrono::high_resolution_clock::time_point last_update{};
28};
29} // namespace VideoCore
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 9e9b38214..805bb954b 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -661,6 +661,8 @@ void Config::ReadRendererValues() {
661 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); 661 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true);
662 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), 662 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"),
663 false); 663 false);
664 ReadSettingGlobal(Settings::values.use_asynchronous_shaders,
665 QStringLiteral("use_asynchronous_shaders"), false);
664 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), 666 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
665 true); 667 true);
666 ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); 668 ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false);
@@ -1145,6 +1147,8 @@ void Config::SaveRendererValues() {
1145 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); 1147 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
1146 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), 1148 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"),
1147 Settings::values.use_assembly_shaders, false); 1149 Settings::values.use_assembly_shaders, false);
1150 WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"),
1151 Settings::values.use_asynchronous_shaders, false);
1148 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, 1152 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time,
1149 true); 1153 true);
1150 WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, 1154 WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode,
@@ -1368,11 +1372,13 @@ void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool
1368 1372
1369void Config::Reload() { 1373void Config::Reload() {
1370 ReadValues(); 1374 ReadValues();
1375 Settings::Sanitize();
1371 // To apply default value changes 1376 // To apply default value changes
1372 SaveValues(); 1377 SaveValues();
1373 Settings::Apply(); 1378 Settings::Apply();
1374} 1379}
1375 1380
1376void Config::Save() { 1381void Config::Save() {
1382 Settings::Sanitize();
1377 SaveValues(); 1383 SaveValues();
1378} 1384}
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 7c0fa7ec5..ce30188cd 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -24,6 +24,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
24 const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); 24 const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
25 ui->use_vsync->setEnabled(runtime_lock); 25 ui->use_vsync->setEnabled(runtime_lock);
26 ui->use_assembly_shaders->setEnabled(runtime_lock); 26 ui->use_assembly_shaders->setEnabled(runtime_lock);
27 ui->use_asynchronous_shaders->setEnabled(runtime_lock);
27 ui->force_30fps_mode->setEnabled(runtime_lock); 28 ui->force_30fps_mode->setEnabled(runtime_lock);
28 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
29 30
@@ -32,6 +33,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
32 static_cast<int>(Settings::values.gpu_accuracy.GetValue())); 33 static_cast<int>(Settings::values.gpu_accuracy.GetValue()));
33 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); 34 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
34 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); 35 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
36 ui->use_asynchronous_shaders->setChecked(
37 Settings::values.use_asynchronous_shaders.GetValue());
35 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); 38 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
36 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); 39 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
37 ui->anisotropic_filtering_combobox->setCurrentIndex( 40 ui->anisotropic_filtering_combobox->setCurrentIndex(
@@ -41,6 +44,10 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
41 ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync); 44 ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync);
42 ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders, 45 ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders,
43 &Settings::values.use_assembly_shaders); 46 &Settings::values.use_assembly_shaders);
47 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders,
48 &Settings::values.use_asynchronous_shaders);
49 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders,
50 &Settings::values.use_asynchronous_shaders);
44 ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time, 51 ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time,
45 &Settings::values.use_fast_gpu_time); 52 &Settings::values.use_fast_gpu_time);
46 ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode, 53 ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode,
@@ -67,6 +74,14 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
67 if (Settings::values.use_assembly_shaders.UsingGlobal()) { 74 if (Settings::values.use_assembly_shaders.UsingGlobal()) {
68 Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); 75 Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked());
69 } 76 }
77 if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
78 Settings::values.use_asynchronous_shaders.SetValue(
79 ui->use_asynchronous_shaders->isChecked());
80 }
81 if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
82 Settings::values.use_asynchronous_shaders.SetValue(
83 ui->use_asynchronous_shaders->isChecked());
84 }
70 if (Settings::values.use_fast_gpu_time.UsingGlobal()) { 85 if (Settings::values.use_fast_gpu_time.UsingGlobal()) {
71 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); 86 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked());
72 } 87 }
@@ -83,6 +98,10 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
83 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); 98 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync);
84 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, 99 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
85 ui->use_assembly_shaders); 100 ui->use_assembly_shaders);
101 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
102 ui->use_asynchronous_shaders);
103 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
104 ui->use_asynchronous_shaders);
86 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, 105 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
87 ui->use_fast_gpu_time); 106 ui->use_fast_gpu_time);
88 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, 107 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode,
@@ -117,6 +136,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
117 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); 136 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
118 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); 137 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
119 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); 138 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal());
139 ui->use_asynchronous_shaders->setEnabled(
140 Settings::values.use_asynchronous_shaders.UsingGlobal());
120 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); 141 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
121 ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); 142 ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal());
122 ui->anisotropic_filtering_combobox->setEnabled( 143 ui->anisotropic_filtering_combobox->setEnabled(
@@ -128,6 +149,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
128 ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); 149 ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy);
129 ui->use_vsync->setTristate(true); 150 ui->use_vsync->setTristate(true);
130 ui->use_assembly_shaders->setTristate(true); 151 ui->use_assembly_shaders->setTristate(true);
152 ui->use_asynchronous_shaders->setTristate(true);
131 ui->use_fast_gpu_time->setTristate(true); 153 ui->use_fast_gpu_time->setTristate(true);
132 ui->force_30fps_mode->setTristate(true); 154 ui->force_30fps_mode->setTristate(true);
133 ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); 155 ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox);
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 0021607ac..71e7dfe5e 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -73,6 +73,16 @@
73 </widget> 73 </widget>
74 </item> 74 </item>
75 <item> 75 <item>
76 <widget class="QCheckBox" name="use_asynchronous_shaders">
77 <property name="toolTip">
78 <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string>
79 </property>
80 <property name="text">
81 <string>Use asynchronous shader building (experimental, OpenGL or Assembly shaders only)</string>
82 </property>
83 </widget>
84 </item>
85 <item>
76 <widget class="QCheckBox" name="force_30fps_mode"> 86 <widget class="QCheckBox" name="force_30fps_mode">
77 <property name="text"> 87 <property name="text">
78 <string>Force 30 FPS mode</string> 88 <string>Force 30 FPS mode</string>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 432379705..6909d65d0 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -94,6 +94,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
94#include "core/perf_stats.h" 94#include "core/perf_stats.h"
95#include "core/settings.h" 95#include "core/settings.h"
96#include "core/telemetry_session.h" 96#include "core/telemetry_session.h"
97#include "video_core/gpu.h"
98#include "video_core/shader_notify.h"
97#include "yuzu/about_dialog.h" 99#include "yuzu/about_dialog.h"
98#include "yuzu/bootmanager.h" 100#include "yuzu/bootmanager.h"
99#include "yuzu/compatdb.h" 101#include "yuzu/compatdb.h"
@@ -279,17 +281,21 @@ GMainWindow::~GMainWindow() {
279} 281}
280 282
281void GMainWindow::ProfileSelectorSelectProfile() { 283void GMainWindow::ProfileSelectorSelectProfile() {
282 QtProfileSelectionDialog dialog(this); 284 const Service::Account::ProfileManager manager;
283 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 285 int index = 0;
284 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); 286 if (manager.GetUserCount() != 1) {
285 dialog.setWindowModality(Qt::WindowModal); 287 QtProfileSelectionDialog dialog(this);
286 if (dialog.exec() == QDialog::Rejected) { 288 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
287 emit ProfileSelectorFinishedSelection(std::nullopt); 289 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
288 return; 290 dialog.setWindowModality(Qt::WindowModal);
291 if (dialog.exec() == QDialog::Rejected) {
292 emit ProfileSelectorFinishedSelection(std::nullopt);
293 return;
294 }
295 index = dialog.GetIndex();
289 } 296 }
290 297
291 Service::Account::ProfileManager manager; 298 const auto uuid = manager.GetUser(static_cast<std::size_t>(index));
292 const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex()));
293 if (!uuid.has_value()) { 299 if (!uuid.has_value()) {
294 emit ProfileSelectorFinishedSelection(std::nullopt); 300 emit ProfileSelectorFinishedSelection(std::nullopt);
295 return; 301 return;
@@ -494,6 +500,8 @@ void GMainWindow::InitializeWidgets() {
494 message_label->setAlignment(Qt::AlignLeft); 500 message_label->setAlignment(Qt::AlignLeft);
495 statusBar()->addPermanentWidget(message_label, 1); 501 statusBar()->addPermanentWidget(message_label, 1);
496 502
503 shader_building_label = new QLabel();
504 shader_building_label->setToolTip(tr("The amount of shaders currently being built"));
497 emu_speed_label = new QLabel(); 505 emu_speed_label = new QLabel();
498 emu_speed_label->setToolTip( 506 emu_speed_label->setToolTip(
499 tr("Current emulation speed. Values higher or lower than 100% " 507 tr("Current emulation speed. Values higher or lower than 100% "
@@ -506,7 +514,8 @@ void GMainWindow::InitializeWidgets() {
506 tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For " 514 tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For "
507 "full-speed emulation this should be at most 16.67 ms.")); 515 "full-speed emulation this should be at most 16.67 ms."));
508 516
509 for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) { 517 for (auto& label :
518 {shader_building_label, emu_speed_label, game_fps_label, emu_frametime_label}) {
510 label->setVisible(false); 519 label->setVisible(false);
511 label->setFrameStyle(QFrame::NoFrame); 520 label->setFrameStyle(QFrame::NoFrame);
512 label->setContentsMargins(4, 0, 4, 0); 521 label->setContentsMargins(4, 0, 4, 0);
@@ -1172,6 +1181,7 @@ void GMainWindow::ShutdownGame() {
1172 1181
1173 // Disable status bar updates 1182 // Disable status bar updates
1174 status_bar_update_timer.stop(); 1183 status_bar_update_timer.stop();
1184 shader_building_label->setVisible(false);
1175 emu_speed_label->setVisible(false); 1185 emu_speed_label->setVisible(false);
1176 game_fps_label->setVisible(false); 1186 game_fps_label->setVisible(false);
1177 emu_frametime_label->setVisible(false); 1187 emu_frametime_label->setVisible(false);
@@ -1755,7 +1765,7 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
1755 *nsp, true, qt_raw_copy); 1765 *nsp, true, qt_raw_copy);
1756 if (res == FileSys::InstallResult::Success) { 1766 if (res == FileSys::InstallResult::Success) {
1757 return InstallResult::Success; 1767 return InstallResult::Success;
1758 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { 1768 } else if (res == FileSys::InstallResult::OverwriteExisting) {
1759 return InstallResult::Overwrite; 1769 return InstallResult::Overwrite;
1760 } else { 1770 } else {
1761 return InstallResult::Failure; 1771 return InstallResult::Failure;
@@ -1842,7 +1852,7 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) {
1842 1852
1843 if (res == FileSys::InstallResult::Success) { 1853 if (res == FileSys::InstallResult::Success) {
1844 return InstallResult::Success; 1854 return InstallResult::Success;
1845 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { 1855 } else if (res == FileSys::InstallResult::OverwriteExisting) {
1846 return InstallResult::Overwrite; 1856 return InstallResult::Overwrite;
1847 } else { 1857 } else {
1848 return InstallResult::Failure; 1858 return InstallResult::Failure;
@@ -2182,6 +2192,17 @@ void GMainWindow::UpdateStatusBar() {
2182 } 2192 }
2183 2193
2184 auto results = Core::System::GetInstance().GetAndResetPerfStats(); 2194 auto results = Core::System::GetInstance().GetAndResetPerfStats();
2195 auto& shader_notify = Core::System::GetInstance().GPU().ShaderNotify();
2196 const auto shaders_building = shader_notify.GetShadersBuilding();
2197
2198 if (shaders_building != 0) {
2199 shader_building_label->setText(
2200 tr("Building: %1 shader").arg(shaders_building) +
2201 (shaders_building != 1 ? QString::fromStdString("s") : QString::fromStdString("")));
2202 shader_building_label->setVisible(true);
2203 } else {
2204 shader_building_label->setVisible(false);
2205 }
2185 2206
2186 if (Settings::values.use_frame_limit.GetValue()) { 2207 if (Settings::values.use_frame_limit.GetValue()) {
2187 emu_speed_label->setText(tr("Speed: %1% / %2%") 2208 emu_speed_label->setText(tr("Speed: %1% / %2%")
@@ -2311,9 +2332,12 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
2311 if (behavior == ReinitializeKeyBehavior::Warning) { 2332 if (behavior == ReinitializeKeyBehavior::Warning) {
2312 const auto res = QMessageBox::information( 2333 const auto res = QMessageBox::information(
2313 this, tr("Confirm Key Rederivation"), 2334 this, tr("Confirm Key Rederivation"),
2314 tr("You are about to force rederive all of your keys. \nIf you do not know what this " 2335 tr("You are about to force rederive all of your keys. \nIf you do not know what "
2315 "means or what you are doing, \nthis is a potentially destructive action. \nPlease " 2336 "this "
2316 "make sure this is what you want \nand optionally make backups.\n\nThis will delete " 2337 "means or what you are doing, \nthis is a potentially destructive action. "
2338 "\nPlease "
2339 "make sure this is what you want \nand optionally make backups.\n\nThis will "
2340 "delete "
2317 "your autogenerated key files and re-run the key derivation module."), 2341 "your autogenerated key files and re-run the key derivation module."),
2318 QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); 2342 QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel});
2319 2343
@@ -2624,8 +2648,8 @@ int main(int argc, char* argv[]) {
2624 2648
2625#ifdef __APPLE__ 2649#ifdef __APPLE__
2626 // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". 2650 // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/".
2627 // But since we require the working directory to be the executable path for the location of the 2651 // But since we require the working directory to be the executable path for the location of
2628 // user folder in the Qt Frontend, we need to cd into that working directory 2652 // the user folder in the Qt Frontend, we need to cd into that working directory
2629 const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; 2653 const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + "..";
2630 chdir(bin_path.c_str()); 2654 chdir(bin_path.c_str());
2631#endif 2655#endif
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index adff65fb5..59d9073ae 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -248,6 +248,7 @@ private:
248 248
249 // Status bar elements 249 // Status bar elements
250 QLabel* message_label = nullptr; 250 QLabel* message_label = nullptr;
251 QLabel* shader_building_label = nullptr;
251 QLabel* emu_speed_label = nullptr; 252 QLabel* emu_speed_label = nullptr;
252 QLabel* game_fps_label = nullptr; 253 QLabel* game_fps_label = nullptr;
253 QLabel* emu_frametime_label = nullptr; 254 QLabel* emu_frametime_label = nullptr;
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 7773228c8..c2a2982fb 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -394,6 +394,10 @@ void Config::ReadValues() {
394 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); 394 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1)));
395 Settings::values.use_assembly_shaders.SetValue( 395 Settings::values.use_assembly_shaders.SetValue(
396 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false)); 396 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false));
397 Settings::values.use_asynchronous_shaders.SetValue(
398 sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false));
399 Settings::values.use_asynchronous_shaders.SetValue(
400 sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false));
397 Settings::values.use_fast_gpu_time.SetValue( 401 Settings::values.use_fast_gpu_time.SetValue(
398 sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); 402 sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true));
399 403
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 5bed47fd7..aa9e40380 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -166,6 +166,10 @@ use_vsync =
166# 0 (default): Off, 1: On 166# 0 (default): Off, 1: On
167use_assembly_shaders = 167use_assembly_shaders =
168 168
169# Whether to allow asynchronous shader building.
170# 0 (default): Off, 1: On
171use_asynchronous_shaders =
172
169# Turns on the frame limiter, which will limit frames output to the target game speed 173# Turns on the frame limiter, which will limit frames output to the target game speed
170# 0: Off, 1: On (default) 174# 0: Off, 1: On (default)
171use_frame_limit = 175use_frame_limit =