summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/bounded_threadsafe_queue.h5
-rw-r--r--src/common/string_util.cpp14
-rw-r--r--src/common/string_util.h8
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp2
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp35
-rw-r--r--src/core/hle/service/mii/mii_manager.h7
-rw-r--r--src/core/hle/service/mii/types.h60
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.cpp6
-rw-r--r--src/core/hle/service/nfp/nfp_device.cpp89
-rw-r--r--src/core/hle/service/nfp/nfp_device.h2
-rw-r--r--src/core/hle/service/nfp/nfp_types.h10
-rw-r--r--src/video_core/gpu_thread.cpp3
-rw-r--r--src/video_core/gpu_thread.h4
13 files changed, 176 insertions, 69 deletions
diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h
index 21217801e..14e887c70 100644
--- a/src/common/bounded_threadsafe_queue.h
+++ b/src/common/bounded_threadsafe_queue.h
@@ -9,10 +9,11 @@
9#include <memory> 9#include <memory>
10#include <mutex> 10#include <mutex>
11#include <new> 11#include <new>
12#include <stop_token>
13#include <type_traits> 12#include <type_traits>
14#include <utility> 13#include <utility>
15 14
15#include "common/polyfill_thread.h"
16
16namespace Common { 17namespace Common {
17 18
18#if defined(__cpp_lib_hardware_interference_size) 19#if defined(__cpp_lib_hardware_interference_size)
@@ -78,7 +79,7 @@ public:
78 auto& slot = slots[idx(tail)]; 79 auto& slot = slots[idx(tail)];
79 if (!slot.turn.test()) { 80 if (!slot.turn.test()) {
80 std::unique_lock lock{cv_mutex}; 81 std::unique_lock lock{cv_mutex};
81 cv.wait(lock, stop, [&slot] { return slot.turn.test(); }); 82 Common::CondvarWait(cv, lock, stop, [&slot] { return slot.turn.test(); });
82 } 83 }
83 v = slot.move(); 84 v = slot.move();
84 slot.destroy(); 85 slot.destroy();
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index e0b6180c5..feab1653d 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -125,18 +125,18 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
125 return result; 125 return result;
126} 126}
127 127
128std::string UTF16ToUTF8(const std::u16string& input) { 128std::string UTF16ToUTF8(std::u16string_view input) {
129 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 129 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
130 return convert.to_bytes(input); 130 return convert.to_bytes(input.data(), input.data() + input.size());
131} 131}
132 132
133std::u16string UTF8ToUTF16(const std::string& input) { 133std::u16string UTF8ToUTF16(std::string_view input) {
134 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 134 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
135 return convert.from_bytes(input); 135 return convert.from_bytes(input.data(), input.data() + input.size());
136} 136}
137 137
138#ifdef _WIN32 138#ifdef _WIN32
139static std::wstring CPToUTF16(u32 code_page, const std::string& input) { 139static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
140 const auto size = 140 const auto size =
141 MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); 141 MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0);
142 142
@@ -154,7 +154,7 @@ static std::wstring CPToUTF16(u32 code_page, const std::string& input) {
154 return output; 154 return output;
155} 155}
156 156
157std::string UTF16ToUTF8(const std::wstring& input) { 157std::string UTF16ToUTF8(std::wstring_view input) {
158 const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), 158 const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
159 nullptr, 0, nullptr, nullptr); 159 nullptr, 0, nullptr, nullptr);
160 if (size == 0) { 160 if (size == 0) {
@@ -172,7 +172,7 @@ std::string UTF16ToUTF8(const std::wstring& input) {
172 return output; 172 return output;
173} 173}
174 174
175std::wstring UTF8ToUTF16W(const std::string& input) { 175std::wstring UTF8ToUTF16W(std::string_view input) {
176 return CPToUTF16(CP_UTF8, input); 176 return CPToUTF16(CP_UTF8, input);
177} 177}
178 178
diff --git a/src/common/string_util.h b/src/common/string_util.h
index f8aecc875..c351f1a0c 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -36,12 +36,12 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
36[[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src, 36[[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
37 const std::string& dest); 37 const std::string& dest);
38 38
39[[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input); 39[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
40[[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input); 40[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
41 41
42#ifdef _WIN32 42#ifdef _WIN32
43[[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input); 43[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
44[[nodiscard]] std::wstring UTF8ToUTF16W(const std::string& str); 44[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str);
45 45
46#endif 46#endif
47 47
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 46fd0f2ea..2a8c09a79 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -17,7 +17,7 @@ Result SendSyncRequest(Core::System& system, Handle handle) {
17 GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle); 17 GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle);
18 R_UNLESS(session.IsNotNull(), ResultInvalidHandle); 18 R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
19 19
20 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); 20 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
21 21
22 R_RETURN(session->SendSyncRequest()); 22 R_RETURN(session->SendSyncRequest());
23} 23}
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 3a2fe938f..c920650f5 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -510,7 +510,7 @@ CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
510 return mii; 510 return mii;
511} 511}
512 512
513Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { 513Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const {
514 Service::Mii::MiiManager manager; 514 Service::Mii::MiiManager manager;
515 Ver3StoreData mii_v3{}; 515 Ver3StoreData mii_v3{};
516 516
@@ -534,16 +534,13 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
534 mii_v3.region_information.character_set.Assign(mii.font_region); 534 mii_v3.region_information.character_set.Assign(mii.font_region);
535 535
536 mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type); 536 mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type);
537 mii_v3.appearance_bits1.skin_color.Assign(mii.faceline_color);
538 mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle); 537 mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle);
539 mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make); 538 mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make);
540 539
541 mii_v3.hair_style = mii.hair_type; 540 mii_v3.hair_style = mii.hair_type;
542 mii_v3.appearance_bits3.hair_color.Assign(mii.hair_color);
543 mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip); 541 mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip);
544 542
545 mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type); 543 mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type);
546 mii_v3.appearance_bits4.eye_color.Assign(mii.eye_color);
547 mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale); 544 mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale);
548 mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect); 545 mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect);
549 mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate); 546 mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate);
@@ -551,7 +548,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
551 mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y); 548 mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y);
552 549
553 mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type); 550 mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type);
554 mii_v3.appearance_bits5.eyebrow_color.Assign(mii.eyebrow_color);
555 mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale); 551 mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale);
556 mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect); 552 mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect);
557 mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate); 553 mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate);
@@ -563,7 +559,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
563 mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y); 559 mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y);
564 560
565 mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type); 561 mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type);
566 mii_v3.appearance_bits7.mouth_color.Assign(mii.mouth_color);
567 mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale); 562 mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale);
568 mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect); 563 mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect);
569 mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y); 564 mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y);
@@ -573,10 +568,7 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
573 mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y); 568 mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y);
574 569
575 mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); 570 mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type);
576 mii_v3.appearance_bits9.facial_hair_color.Assign(mii.beard_color);
577 571
578 mii_v3.appearance_bits10.glasses_type.Assign(mii.glasses_type);
579 mii_v3.appearance_bits10.glasses_color.Assign(mii.glasses_color);
580 mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); 572 mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale);
581 mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); 573 mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y);
582 574
@@ -585,11 +577,36 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
585 mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); 577 mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x);
586 mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); 578 mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y);
587 579
580 // These types are converted to V3 from a table
581 mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]);
582 mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]);
583 mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]);
584 mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]);
585 mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]);
586 mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]);
587 mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]);
588 mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]);
589
590 mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16));
591
588 // TODO: Validate mii_v3 data 592 // TODO: Validate mii_v3 data
589 593
590 return mii_v3; 594 return mii_v3;
591} 595}
592 596
597NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const {
598 return {
599 .faceline_color = static_cast<u8>(mii.faceline_color & 0xf),
600 .hair_color = static_cast<u8>(mii.hair_color & 0x7f),
601 .eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
602 .eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
603 .mouth_color = static_cast<u8>(mii.mouth_color & 0x7f),
604 .beard_color = static_cast<u8>(mii.beard_color & 0x7f),
605 .glass_color = static_cast<u8>(mii.glasses_color & 0x7f),
606 .glass_type = static_cast<u8>(mii.glasses_type & 0x1f),
607 };
608}
609
593bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { 610bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
594 bool is_valid = mii_v3.version == 0 || mii_v3.version == 3; 611 bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
595 612
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index 83ad3d343..5525fcd1c 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -23,11 +23,16 @@ public:
23 CharInfo BuildRandom(Age age, Gender gender, Race race); 23 CharInfo BuildRandom(Age age, Gender gender, Race race);
24 CharInfo BuildDefault(std::size_t index); 24 CharInfo BuildDefault(std::size_t index);
25 CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; 25 CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
26 Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const;
27 bool ValidateV3Info(const Ver3StoreData& mii_v3) const; 26 bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
28 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); 27 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
29 Result GetIndex(const CharInfo& info, u32& index); 28 Result GetIndex(const CharInfo& info, u32& index);
30 29
30 // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
31 Ver3StoreData BuildFromStoreData(const CharInfo& mii) const;
32
33 // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData
34 NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const;
35
31private: 36private:
32 const Common::UUID user_id{}; 37 const Common::UUID user_id{};
33 u64 update_counter{}; 38 u64 update_counter{};
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
index 9e3247397..c48d08d79 100644
--- a/src/core/hle/service/mii/types.h
+++ b/src/core/hle/service/mii/types.h
@@ -365,10 +365,68 @@ struct Ver3StoreData {
365 } appearance_bits11; 365 } appearance_bits11;
366 366
367 std::array<u16_le, 0xA> author_name; 367 std::array<u16_le, 0xA> author_name;
368 INSERT_PADDING_BYTES(0x4); 368 INSERT_PADDING_BYTES(0x2);
369 u16_be crc;
369}; 370};
370static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size"); 371static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
371 372
373struct NfpStoreDataExtension {
374 u8 faceline_color;
375 u8 hair_color;
376 u8 eye_color;
377 u8 eyebrow_color;
378 u8 mouth_color;
379 u8 beard_color;
380 u8 glass_color;
381 u8 glass_type;
382};
383static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
384
385constexpr std::array<u8, 0x10> Ver3FacelineColorTable{
386 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
387};
388
389constexpr std::array<u8, 100> Ver3HairColorTable{
390 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
391 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
392 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
393 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
394 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
395 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
396};
397
398constexpr std::array<u8, 100> Ver3EyeColorTable{
399 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
400 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
401 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
402 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
403 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
404 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
405};
406
407constexpr std::array<u8, 100> Ver3MouthlineColorTable{
408 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
409 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
410 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
411 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
412 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
413 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
414};
415
416constexpr std::array<u8, 100> Ver3GlassColorTable{
417 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
418 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
419 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
420 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
421 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
422 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
423};
424
425constexpr std::array<u8, 20> Ver3GlassTypeTable{
426 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
427 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
428};
429
372struct MiiStoreData { 430struct MiiStoreData {
373 using Name = std::array<char16_t, 10>; 431 using Name = std::array<char16_t, 10>;
374 432
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp
index ad73edbda..bba862fb2 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfp/amiibo_crypto.cpp
@@ -88,8 +88,9 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
88 encoded_data.application_area_id = nfc_data.user_memory.application_area_id; 88 encoded_data.application_area_id = nfc_data.user_memory.application_area_id;
89 encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; 89 encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte;
90 encoded_data.unknown = nfc_data.user_memory.unknown; 90 encoded_data.unknown = nfc_data.user_memory.unknown;
91 encoded_data.mii_extension = nfc_data.user_memory.mii_extension;
91 encoded_data.unknown2 = nfc_data.user_memory.unknown2; 92 encoded_data.unknown2 = nfc_data.user_memory.unknown2;
92 encoded_data.application_area_crc = nfc_data.user_memory.application_area_crc; 93 encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc;
93 encoded_data.application_area = nfc_data.user_memory.application_area; 94 encoded_data.application_area = nfc_data.user_memory.application_area;
94 encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; 95 encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag;
95 encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; 96 encoded_data.lock_bytes = nfc_data.uuid.lock_bytes;
@@ -122,8 +123,9 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
122 nfc_data.user_memory.application_area_id = encoded_data.application_area_id; 123 nfc_data.user_memory.application_area_id = encoded_data.application_area_id;
123 nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; 124 nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte;
124 nfc_data.user_memory.unknown = encoded_data.unknown; 125 nfc_data.user_memory.unknown = encoded_data.unknown;
126 nfc_data.user_memory.mii_extension = encoded_data.mii_extension;
125 nfc_data.user_memory.unknown2 = encoded_data.unknown2; 127 nfc_data.user_memory.unknown2 = encoded_data.unknown2;
126 nfc_data.user_memory.application_area_crc = encoded_data.application_area_crc; 128 nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc;
127 nfc_data.user_memory.application_area = encoded_data.application_area; 129 nfc_data.user_memory.application_area = encoded_data.application_area;
128 nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag; 130 nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag;
129 nfc_data.user_memory.model_info = encoded_data.model_info; 131 nfc_data.user_memory.model_info = encoded_data.model_info;
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
index ddff90d6a..268337d2e 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfp/nfp_device.cpp
@@ -3,6 +3,17 @@
3 3
4#include <array> 4#include <array>
5 5
6#ifdef _MSC_VER
7#pragma warning(push)
8#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used
9#endif
10
11#include <boost/crc.hpp>
12
13#ifdef _MSC_VER
14#pragma warning(pop)
15#endif
16
6#include "common/input.h" 17#include "common/input.h"
7#include "common/logging/log.h" 18#include "common/logging/log.h"
8#include "common/string_util.h" 19#include "common/string_util.h"
@@ -448,7 +459,7 @@ Result NfpDevice::DeleteRegisterInfo() {
448 rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8)); 459 rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8));
449 rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32)); 460 rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32));
450 rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32)); 461 rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32));
451 rng.GenerateRandomBytes(&tag_data.application_area_crc, sizeof(u32)); 462 rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32));
452 rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32)); 463 rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32));
453 tag_data.settings.settings.font_region.Assign(0); 464 tag_data.settings.settings.font_region.Assign(0);
454 tag_data.settings.settings.amiibo_initialized.Assign(0); 465 tag_data.settings.settings.amiibo_initialized.Assign(0);
@@ -471,6 +482,7 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) {
471 } 482 }
472 483
473 Service::Mii::MiiManager manager; 484 Service::Mii::MiiManager manager;
485 const auto mii = manager.BuildDefault(0);
474 auto& settings = tag_data.settings; 486 auto& settings = tag_data.settings;
475 487
476 if (tag_data.settings.settings.amiibo_initialized == 0) { 488 if (tag_data.settings.settings.amiibo_initialized == 0) {
@@ -479,16 +491,15 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) {
479 } 491 }
480 492
481 SetAmiiboName(settings, amiibo_name); 493 SetAmiiboName(settings, amiibo_name);
482 tag_data.owner_mii = manager.ConvertCharInfoToV3(manager.BuildDefault(0)); 494 tag_data.owner_mii = manager.BuildFromStoreData(mii);
495 tag_data.mii_extension = manager.SetFromStoreData(mii);
483 tag_data.unknown = 0; 496 tag_data.unknown = 0;
484 tag_data.unknown2[6] = 0; 497 tag_data.unknown2 = {};
485 settings.country_code_id = 0; 498 settings.country_code_id = 0;
486 settings.settings.font_region.Assign(0); 499 settings.settings.font_region.Assign(0);
487 settings.settings.amiibo_initialized.Assign(1); 500 settings.settings.amiibo_initialized.Assign(1);
488 501
489 // TODO: this is a mix of tag.file input 502 UpdateRegisterInfoCrc();
490 std::array<u8, 0x7e> unknown_input{};
491 tag_data.application_area_crc = CalculateCrc(unknown_input);
492 503
493 return Flush(); 504 return Flush();
494} 505}
@@ -685,6 +696,11 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat
685 return WrongDeviceState; 696 return WrongDeviceState;
686 } 697 }
687 698
699 if (is_app_area_open) {
700 LOG_ERROR(Service_NFP, "Application area is open");
701 return WrongDeviceState;
702 }
703
688 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { 704 if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) {
689 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); 705 LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
690 return WrongDeviceState; 706 return WrongDeviceState;
@@ -715,10 +731,9 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat
715 tag_data.settings.settings.appdata_initialized.Assign(1); 731 tag_data.settings.settings.appdata_initialized.Assign(1);
716 tag_data.application_area_id = access_id; 732 tag_data.application_area_id = access_id;
717 tag_data.unknown = {}; 733 tag_data.unknown = {};
734 tag_data.unknown2 = {};
718 735
719 // TODO: this is a mix of tag_data input 736 UpdateRegisterInfoCrc();
720 std::array<u8, 0x7e> unknown_input{};
721 tag_data.application_area_crc = CalculateCrc(unknown_input);
722 737
723 return Flush(); 738 return Flush();
724} 739}
@@ -752,6 +767,10 @@ Result NfpDevice::DeleteApplicationArea() {
752 rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); 767 rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8));
753 tag_data.settings.settings.appdata_initialized.Assign(0); 768 tag_data.settings.settings.appdata_initialized.Assign(0);
754 tag_data.unknown = {}; 769 tag_data.unknown = {};
770 tag_data.unknown2 = {};
771 is_app_area_open = false;
772
773 UpdateRegisterInfoCrc();
755 774
756 return Flush(); 775 return Flush();
757} 776}
@@ -835,32 +854,34 @@ void NfpDevice::UpdateSettingsCrc() {
835 854
836 // TODO: this reads data from a global, find what it is 855 // TODO: this reads data from a global, find what it is
837 std::array<u8, 8> unknown_input{}; 856 std::array<u8, 8> unknown_input{};
838 settings.crc = CalculateCrc(unknown_input); 857 boost::crc_32_type crc;
839} 858 crc.process_bytes(&unknown_input, sizeof(unknown_input));
840 859 settings.crc = crc.checksum();
841u32 NfpDevice::CalculateCrc(std::span<const u8> data) { 860}
842 constexpr u32 magic = 0xedb88320; 861
843 u32 crc = 0xffffffff; 862void NfpDevice::UpdateRegisterInfoCrc() {
844 863#pragma pack(push, 1)
845 if (data.size() == 0) { 864 struct CrcData {
846 return 0; 865 Mii::Ver3StoreData mii;
847 } 866 u8 application_id_byte;
848 867 u8 unknown;
849 for (u8 input : data) { 868 Mii::NfpStoreDataExtension mii_extension;
850 u32 temp = (crc ^ input) >> 1; 869 std::array<u32, 0x5> unknown2;
851 if (((crc ^ input) & 1) != 0) { 870 };
852 temp = temp ^ magic; 871 static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size");
853 } 872#pragma pack(pop)
854 873
855 for (std::size_t step = 0; step < 7; ++step) { 874 const CrcData crc_data{
856 crc = temp >> 1; 875 .mii = tag_data.owner_mii,
857 if ((temp & 1) != 0) { 876 .application_id_byte = tag_data.application_id_byte,
858 crc = temp >> 1 ^ magic; 877 .unknown = tag_data.unknown,
859 } 878 .mii_extension = tag_data.mii_extension,
860 } 879 .unknown2 = tag_data.unknown2,
861 } 880 };
862 881
863 return ~crc; 882 boost::crc_32_type crc;
883 crc.process_bytes(&crc_data, sizeof(CrcData));
884 tag_data.register_info_crc = crc.checksum();
864} 885}
865 886
866} // namespace Service::NFP 887} // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
index 06386401d..8813df998 100644
--- a/src/core/hle/service/nfp/nfp_device.h
+++ b/src/core/hle/service/nfp/nfp_device.h
@@ -80,7 +80,7 @@ private:
80 AmiiboDate GetAmiiboDate(s64 posix_time) const; 80 AmiiboDate GetAmiiboDate(s64 posix_time) const;
81 u64 RemoveVersionByte(u64 application_id) const; 81 u64 RemoveVersionByte(u64 application_id) const;
82 void UpdateSettingsCrc(); 82 void UpdateSettingsCrc();
83 u32 CalculateCrc(std::span<const u8>); 83 void UpdateRegisterInfoCrc();
84 84
85 bool is_controller_set{}; 85 bool is_controller_set{};
86 int callback_key; 86 int callback_key;
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 142343d6e..b3599a513 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -259,8 +259,9 @@ struct EncryptedAmiiboFile {
259 u32_be application_area_id; // Encrypted Game id 259 u32_be application_area_id; // Encrypted Game id
260 u8 application_id_byte; 260 u8 application_id_byte;
261 u8 unknown; 261 u8 unknown;
262 std::array<u32, 0x7> unknown2; 262 Service::Mii::NfpStoreDataExtension mii_extension;
263 u32_be application_area_crc; 263 std::array<u32, 0x5> unknown2;
264 u32_be register_info_crc;
264 ApplicationArea application_area; // Encrypted Game data 265 ApplicationArea application_area; // Encrypted Game data
265}; 266};
266static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); 267static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size");
@@ -280,8 +281,9 @@ struct NTAG215File {
280 u32_be application_area_id; 281 u32_be application_area_id;
281 u8 application_id_byte; 282 u8 application_id_byte;
282 u8 unknown; 283 u8 unknown;
283 std::array<u32, 0x7> unknown2; 284 Service::Mii::NfpStoreDataExtension mii_extension;
284 u32_be application_area_crc; 285 std::array<u32, 0x5> unknown2;
286 u32_be register_info_crc;
285 ApplicationArea application_area; // Encrypted Game data 287 ApplicationArea application_area; // Encrypted Game data
286 HashData hmac_tag; // Hash 288 HashData hmac_tag; // Hash
287 UniqueSerialNumber uid; // Unique serial number 289 UniqueSerialNumber uid; // Unique serial number
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 050b11874..f52f9e28f 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -32,7 +32,8 @@ static void RunThread(std::stop_token stop_token, Core::System& system,
32 VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer(); 32 VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer();
33 33
34 while (!stop_token.stop_requested()) { 34 while (!stop_token.stop_requested()) {
35 CommandDataContainer next = state.queue.PopWait(stop_token); 35 CommandDataContainer next;
36 state.queue.Pop(next, stop_token);
36 if (stop_token.stop_requested()) { 37 if (stop_token.stop_requested()) {
37 break; 38 break;
38 } 39 }
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 90bcb5958..43940bd6d 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -10,8 +10,8 @@
10#include <thread> 10#include <thread>
11#include <variant> 11#include <variant>
12 12
13#include "common/bounded_threadsafe_queue.h"
13#include "common/polyfill_thread.h" 14#include "common/polyfill_thread.h"
14#include "common/threadsafe_queue.h"
15#include "video_core/framebuffer_config.h" 15#include "video_core/framebuffer_config.h"
16 16
17namespace Tegra { 17namespace Tegra {
@@ -97,7 +97,7 @@ struct CommandDataContainer {
97 97
98/// Struct used to synchronize the GPU thread 98/// Struct used to synchronize the GPU thread
99struct SynchState final { 99struct SynchState final {
100 using CommandQueue = Common::MPSCQueue<CommandDataContainer, true>; 100 using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
101 std::mutex write_lock; 101 std::mutex write_lock;
102 CommandQueue queue; 102 CommandQueue queue;
103 u64 last_fence{}; 103 u64 last_fence{};