summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar tech4me2018-08-25 22:43:17 -0700
committerGravatar tech4me2018-08-26 00:11:13 -0700
commitd26a46feed4ef6caeebfb21e69b10c2b913eb4eb (patch)
tree17087ba20c8e3d5cb92596c7a8002f78f008b79f
parentMerge pull request #1173 from lioncash/batch (diff)
downloadyuzu-d26a46feed4ef6caeebfb21e69b10c2b913eb4eb.tar.gz
yuzu-d26a46feed4ef6caeebfb21e69b10c2b913eb4eb.tar.xz
yuzu-d26a46feed4ef6caeebfb21e69b10c2b913eb4eb.zip
set: Fixed GetAvailableLanguageCodes() to follow the max_entries
Rightnow, in games use GetAvailableLanguageCodes(), there is a WriteBuffer() with size larger than the buffer_size. (Core Critical core\hle\kernel\hle_ipc.cpp:WriteBuffer:296: size (0000000000000088) is greater than buffer_size (0000000000000078)) 0x88 = 17(languages) * 8 0x78 = 15(languages) * 8 GetAvailableLanguageCodes() can only support 15 languages. After firmware 4.0.0 there are 17 supported language instead of 15, to enable this GetAvailableLanguageCodes2() need to be used. So GetAvailableLanguageCodes() will be caped at 15 languages. Reference: http://switchbrew.org/index.php/Settings_services
-rw-r--r--src/core/hle/service/set/set.cpp51
-rw-r--r--src/core/hle/service/set/set.h2
2 files changed, 45 insertions, 8 deletions
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index a461e72ec..92b0640e8 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -32,24 +32,59 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{
32 LanguageCode::ZH_HANT, 32 LanguageCode::ZH_HANT,
33}}; 33}};
34 34
35constexpr size_t pre4_0_0_max_entries = 0xF;
36constexpr size_t post4_0_0_max_entries = 0x40;
37
35LanguageCode GetLanguageCodeFromIndex(size_t index) { 38LanguageCode GetLanguageCodeFromIndex(size_t index) {
36 return available_language_codes.at(index); 39 return available_language_codes.at(index);
37} 40}
38 41
39void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { 42template <size_t size>
40 ctx.WriteBuffer(available_language_codes); 43static std::array<LanguageCode, size> MakeLanguageCodeSubset() {
44 std::array<LanguageCode, size> arr;
45 std::copy_n(available_language_codes.begin(), size, arr.begin());
46 return arr;
47}
41 48
49static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, size_t max_size) {
42 IPC::ResponseBuilder rb{ctx, 3}; 50 IPC::ResponseBuilder rb{ctx, 3};
43 rb.Push(RESULT_SUCCESS); 51 rb.Push(RESULT_SUCCESS);
44 rb.Push(static_cast<u32>(available_language_codes.size())); 52 if (available_language_codes.size() > max_size)
53 rb.Push(static_cast<u32>(max_size));
54 else
55 rb.Push(static_cast<u32>(available_language_codes.size()));
56}
57
58void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
59 if (available_language_codes.size() > pre4_0_0_max_entries)
60 ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>());
61 else
62 ctx.WriteBuffer(available_language_codes);
63
64 PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
65
66 LOG_DEBUG(Service_SET, "called");
67}
68
69void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) {
70 if (available_language_codes.size() > post4_0_0_max_entries)
71 ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>());
72 else
73 ctx.WriteBuffer(available_language_codes);
74
75 PushResponseLanguageCode(ctx, post4_0_0_max_entries);
45 76
46 LOG_DEBUG(Service_SET, "called"); 77 LOG_DEBUG(Service_SET, "called");
47} 78}
48 79
49void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { 80void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
50 IPC::ResponseBuilder rb{ctx, 3}; 81 PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
51 rb.Push(RESULT_SUCCESS); 82
52 rb.Push(static_cast<u32>(available_language_codes.size())); 83 LOG_DEBUG(Service_SET, "called");
84}
85
86void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) {
87 PushResponseLanguageCode(ctx, post4_0_0_max_entries);
53 88
54 LOG_DEBUG(Service_SET, "called"); 89 LOG_DEBUG(Service_SET, "called");
55} 90}
@@ -69,8 +104,8 @@ SET::SET() : ServiceFramework("set") {
69 {2, nullptr, "MakeLanguageCode"}, 104 {2, nullptr, "MakeLanguageCode"},
70 {3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"}, 105 {3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
71 {4, nullptr, "GetRegionCode"}, 106 {4, nullptr, "GetRegionCode"},
72 {5, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes2"}, 107 {5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
73 {6, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount2"}, 108 {6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
74 {7, nullptr, "GetKeyCodeMap"}, 109 {7, nullptr, "GetKeyCodeMap"},
75 {8, nullptr, "GetQuestFlag"}, 110 {8, nullptr, "GetQuestFlag"},
76 }; 111 };
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h
index 4232b6162..669e740b7 100644
--- a/src/core/hle/service/set/set.h
+++ b/src/core/hle/service/set/set.h
@@ -38,7 +38,9 @@ public:
38private: 38private:
39 void GetLanguageCode(Kernel::HLERequestContext& ctx); 39 void GetLanguageCode(Kernel::HLERequestContext& ctx);
40 void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx); 40 void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
41 void GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx);
41 void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx); 42 void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
43 void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);
42}; 44};
43 45
44} // namespace Service::Set 46} // namespace Service::Set