set.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <array>
  5. #include <chrono>
  6. #include "common/logging/log.h"
  7. #include "common/settings.h"
  8. #include "core/hle/service/ipc_helpers.h"
  9. #include "core/hle/service/set/set.h"
  10. namespace Service::Set {
  11. namespace {
  12. constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
  13. constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
  14. constexpr Result ResultInvalidLanguage{ErrorModule::Settings, 625};
  15. void PushResponseLanguageCode(HLERequestContext& ctx, std::size_t num_language_codes) {
  16. IPC::ResponseBuilder rb{ctx, 3};
  17. rb.Push(ResultSuccess);
  18. rb.Push(static_cast<u32>(num_language_codes));
  19. }
  20. void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entries) {
  21. const std::size_t requested_amount = ctx.GetWriteBufferNumElements<LanguageCode>();
  22. const std::size_t max_amount = std::min(requested_amount, max_entries);
  23. const std::size_t copy_amount = std::min(available_language_codes.size(), max_amount);
  24. const std::size_t copy_size = copy_amount * sizeof(LanguageCode);
  25. ctx.WriteBuffer(available_language_codes.data(), copy_size);
  26. PushResponseLanguageCode(ctx, copy_amount);
  27. }
  28. void GetKeyCodeMapImpl(HLERequestContext& ctx) {
  29. const auto language_code =
  30. available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
  31. const auto key_code =
  32. std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
  33. [=](const auto& element) { return element.first == language_code; });
  34. KeyboardLayout layout = KeyboardLayout::EnglishUs;
  35. if (key_code == language_to_layout.cend()) {
  36. LOG_ERROR(Service_SET,
  37. "Could not find keyboard layout for language index {}, defaulting to English us",
  38. Settings::values.language_index.GetValue());
  39. } else {
  40. layout = key_code->second;
  41. }
  42. ctx.WriteBuffer(layout);
  43. IPC::ResponseBuilder rb{ctx, 2};
  44. rb.Push(ResultSuccess);
  45. }
  46. } // Anonymous namespace
  47. LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
  48. return available_language_codes.at(index);
  49. }
  50. ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{system_, "set"} {
  51. // clang-format off
  52. static const FunctionInfo functions[] = {
  53. {0, &ISettingsServer::GetLanguageCode, "GetLanguageCode"},
  54. {1, &ISettingsServer::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
  55. {2, &ISettingsServer::MakeLanguageCode, "MakeLanguageCode"},
  56. {3, &ISettingsServer::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
  57. {4, &ISettingsServer::GetRegionCode, "GetRegionCode"},
  58. {5, &ISettingsServer::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
  59. {6, &ISettingsServer::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
  60. {7, &ISettingsServer::GetKeyCodeMap, "GetKeyCodeMap"},
  61. {8, &ISettingsServer::GetQuestFlag, "GetQuestFlag"},
  62. {9, &ISettingsServer::GetKeyCodeMap2, "GetKeyCodeMap2"},
  63. {10, nullptr, "GetFirmwareVersionForDebug"},
  64. {11, &ISettingsServer::GetDeviceNickName, "GetDeviceNickName"},
  65. };
  66. // clang-format on
  67. RegisterHandlers(functions);
  68. }
  69. ISettingsServer::~ISettingsServer() = default;
  70. void ISettingsServer::GetAvailableLanguageCodes(HLERequestContext& ctx) {
  71. LOG_DEBUG(Service_SET, "called");
  72. GetAvailableLanguageCodesImpl(ctx, PRE_4_0_0_MAX_ENTRIES);
  73. }
  74. void ISettingsServer::MakeLanguageCode(HLERequestContext& ctx) {
  75. IPC::RequestParser rp{ctx};
  76. const auto index = rp.Pop<u32>();
  77. if (index >= available_language_codes.size()) {
  78. LOG_ERROR(Service_SET, "Invalid language code index! index={}", index);
  79. IPC::ResponseBuilder rb{ctx, 2};
  80. rb.Push(Set::ResultInvalidLanguage);
  81. return;
  82. }
  83. IPC::ResponseBuilder rb{ctx, 4};
  84. rb.Push(ResultSuccess);
  85. rb.PushEnum(available_language_codes[index]);
  86. }
  87. void ISettingsServer::GetAvailableLanguageCodes2(HLERequestContext& ctx) {
  88. LOG_DEBUG(Service_SET, "called");
  89. GetAvailableLanguageCodesImpl(ctx, POST_4_0_0_MAX_ENTRIES);
  90. }
  91. void ISettingsServer::GetAvailableLanguageCodeCount(HLERequestContext& ctx) {
  92. LOG_DEBUG(Service_SET, "called");
  93. PushResponseLanguageCode(ctx, PRE_4_0_0_MAX_ENTRIES);
  94. }
  95. void ISettingsServer::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) {
  96. LOG_DEBUG(Service_SET, "called");
  97. PushResponseLanguageCode(ctx, POST_4_0_0_MAX_ENTRIES);
  98. }
  99. void ISettingsServer::GetQuestFlag(HLERequestContext& ctx) {
  100. LOG_DEBUG(Service_SET, "called");
  101. IPC::ResponseBuilder rb{ctx, 3};
  102. rb.Push(ResultSuccess);
  103. rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue()));
  104. }
  105. void ISettingsServer::GetLanguageCode(HLERequestContext& ctx) {
  106. LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue());
  107. IPC::ResponseBuilder rb{ctx, 4};
  108. rb.Push(ResultSuccess);
  109. rb.PushEnum(
  110. available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]);
  111. }
  112. void ISettingsServer::GetRegionCode(HLERequestContext& ctx) {
  113. LOG_DEBUG(Service_SET, "called");
  114. IPC::ResponseBuilder rb{ctx, 3};
  115. rb.Push(ResultSuccess);
  116. rb.Push(static_cast<u32>(Settings::values.region_index.GetValue()));
  117. }
  118. void ISettingsServer::GetKeyCodeMap(HLERequestContext& ctx) {
  119. LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
  120. GetKeyCodeMapImpl(ctx);
  121. }
  122. void ISettingsServer::GetKeyCodeMap2(HLERequestContext& ctx) {
  123. LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
  124. GetKeyCodeMapImpl(ctx);
  125. }
  126. void ISettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
  127. LOG_DEBUG(Service_SET, "called");
  128. IPC::ResponseBuilder rb{ctx, 2};
  129. rb.Push(ResultSuccess);
  130. ctx.WriteBuffer(Settings::values.device_name.GetValue());
  131. }
  132. } // namespace Service::Set