forked from suyu/suyu
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
This commit is contained in:
parent
be2f1eabd7
commit
d26a46feed
2 changed files with 45 additions and 8 deletions
|
@ -32,24 +32,59 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{
|
||||||
LanguageCode::ZH_HANT,
|
LanguageCode::ZH_HANT,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
constexpr size_t pre4_0_0_max_entries = 0xF;
|
||||||
|
constexpr size_t post4_0_0_max_entries = 0x40;
|
||||||
|
|
||||||
LanguageCode GetLanguageCodeFromIndex(size_t index) {
|
LanguageCode GetLanguageCodeFromIndex(size_t index) {
|
||||||
return available_language_codes.at(index);
|
return available_language_codes.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
|
template <size_t size>
|
||||||
ctx.WriteBuffer(available_language_codes);
|
static std::array<LanguageCode, size> MakeLanguageCodeSubset() {
|
||||||
|
std::array<LanguageCode, size> arr;
|
||||||
|
std::copy_n(available_language_codes.begin(), size, arr.begin());
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, size_t max_size) {
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
if (available_language_codes.size() > max_size)
|
||||||
|
rb.Push(static_cast<u32>(max_size));
|
||||||
|
else
|
||||||
rb.Push(static_cast<u32>(available_language_codes.size()));
|
rb.Push(static_cast<u32>(available_language_codes.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
|
||||||
|
if (available_language_codes.size() > pre4_0_0_max_entries)
|
||||||
|
ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>());
|
||||||
|
else
|
||||||
|
ctx.WriteBuffer(available_language_codes);
|
||||||
|
|
||||||
|
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_SET, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) {
|
||||||
|
if (available_language_codes.size() > post4_0_0_max_entries)
|
||||||
|
ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>());
|
||||||
|
else
|
||||||
|
ctx.WriteBuffer(available_language_codes);
|
||||||
|
|
||||||
|
PushResponseLanguageCode(ctx, post4_0_0_max_entries);
|
||||||
|
|
||||||
LOG_DEBUG(Service_SET, "called");
|
LOG_DEBUG(Service_SET, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
|
void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.Push(static_cast<u32>(available_language_codes.size()));
|
LOG_DEBUG(Service_SET, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) {
|
||||||
|
PushResponseLanguageCode(ctx, post4_0_0_max_entries);
|
||||||
|
|
||||||
LOG_DEBUG(Service_SET, "called");
|
LOG_DEBUG(Service_SET, "called");
|
||||||
}
|
}
|
||||||
|
@ -69,8 +104,8 @@ SET::SET() : ServiceFramework("set") {
|
||||||
{2, nullptr, "MakeLanguageCode"},
|
{2, nullptr, "MakeLanguageCode"},
|
||||||
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
|
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
|
||||||
{4, nullptr, "GetRegionCode"},
|
{4, nullptr, "GetRegionCode"},
|
||||||
{5, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes2"},
|
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
|
||||||
{6, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount2"},
|
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
|
||||||
{7, nullptr, "GetKeyCodeMap"},
|
{7, nullptr, "GetKeyCodeMap"},
|
||||||
{8, nullptr, "GetQuestFlag"},
|
{8, nullptr, "GetQuestFlag"},
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,9 @@ public:
|
||||||
private:
|
private:
|
||||||
void GetLanguageCode(Kernel::HLERequestContext& ctx);
|
void GetLanguageCode(Kernel::HLERequestContext& ctx);
|
||||||
void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
|
void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
|
||||||
|
void GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx);
|
||||||
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
|
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
|
||||||
|
void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Set
|
} // namespace Service::Set
|
||||||
|
|
Loading…
Reference in a new issue