// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" #include "core/hle/service/set/set.h" #include "core/settings.h" namespace Service::Set { constexpr std::array available_language_codes = {{ LanguageCode::JA, LanguageCode::EN_US, LanguageCode::FR, LanguageCode::DE, LanguageCode::IT, LanguageCode::ES, LanguageCode::ZH_CN, LanguageCode::KO, LanguageCode::NL, LanguageCode::PT, LanguageCode::RU, LanguageCode::ZH_TW, LanguageCode::EN_GB, LanguageCode::FR_CA, LanguageCode::ES_419, LanguageCode::ZH_HANS, LanguageCode::ZH_HANT, }}; constexpr std::size_t pre4_0_0_max_entries = 0xF; constexpr std::size_t post4_0_0_max_entries = 0x40; constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; LanguageCode GetLanguageCodeFromIndex(std::size_t index) { return available_language_codes.at(index); } template static std::array MakeLanguageCodeSubset() { std::array arr; std::copy_n(available_language_codes.begin(), size, arr.begin()); return arr; } static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t max_size) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); if (available_language_codes.size() > max_size) { rb.Push(static_cast(max_size)); } else { rb.Push(static_cast(available_language_codes.size())); } } void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); if (available_language_codes.size() > pre4_0_0_max_entries) { ctx.WriteBuffer(MakeLanguageCodeSubset()); } else { ctx.WriteBuffer(available_language_codes); } PushResponseLanguageCode(ctx, pre4_0_0_max_entries); } void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto index = rp.Pop(); if (index >= available_language_codes.size()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_INVALID_LANGUAGE); return; } IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.PushEnum(available_language_codes[index]); } void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); if (available_language_codes.size() > post4_0_0_max_entries) { ctx.WriteBuffer(MakeLanguageCodeSubset()); } else { ctx.WriteBuffer(available_language_codes); } PushResponseLanguageCode(ctx, post4_0_0_max_entries); } void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); PushResponseLanguageCode(ctx, pre4_0_0_max_entries); } void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) { PushResponseLanguageCode(ctx, post4_0_0_max_entries); LOG_DEBUG(Service_SET, "called"); } void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.PushEnum(available_language_codes[Settings::values.language_index]); } SET::SET() : ServiceFramework("set") { static const FunctionInfo functions[] = { {0, &SET::GetLanguageCode, "GetLanguageCode"}, {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"}, {2, &SET::MakeLanguageCode, "MakeLanguageCode"}, {3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"}, {4, nullptr, "GetRegionCode"}, {5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"}, {6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"}, {7, nullptr, "GetKeyCodeMap"}, {8, nullptr, "GetQuestFlag"}, }; RegisterHandlers(functions); } SET::~SET() = default; } // namespace Service::Set