Merge pull request #11210 from german77/settings

service: set: Implement system settings for Qlaunch
master
liamwhite 2023-08-05 12:58:32 +07:00 committed by GitHub
commit 00d9a9c44e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 724 additions and 120 deletions

@ -22,30 +22,6 @@ class Nvnflinger;
namespace Service::AM { namespace Service::AM {
// This is nn::settings::Language
enum SystemLanguage {
Japanese = 0,
English = 1, // en-US
French = 2,
German = 3,
Italian = 4,
Spanish = 5,
Chinese = 6,
Korean = 7,
Dutch = 8,
Portuguese = 9,
Russian = 10,
Taiwanese = 11,
BritishEnglish = 12, // en-GB
CanadianFrench = 13,
LatinAmericanSpanish = 14, // es-419
// 4.0.0+
SimplifiedChinese = 15,
TraditionalChinese = 16,
// 10.1.0+
BrazilianPortuguese = 17,
};
class AppletMessageQueue { class AppletMessageQueue {
public: public:
// This is nn::am::AppletMessage // This is nn::am::AppletMessage

@ -11,66 +11,6 @@
namespace Service::Set { namespace Service::Set {
namespace { namespace {
constexpr std::array<LanguageCode, 18> 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,
LanguageCode::PT_BR,
}};
enum class KeyboardLayout : u64 {
Japanese = 0,
EnglishUs = 1,
EnglishUsInternational = 2,
EnglishUk = 3,
French = 4,
FrenchCa = 5,
Spanish = 6,
SpanishLatin = 7,
German = 8,
Italian = 9,
Portuguese = 10,
Russian = 11,
Korean = 12,
ChineseSimplified = 13,
ChineseTraditional = 14,
};
constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{
{LanguageCode::JA, KeyboardLayout::Japanese},
{LanguageCode::EN_US, KeyboardLayout::EnglishUs},
{LanguageCode::FR, KeyboardLayout::French},
{LanguageCode::DE, KeyboardLayout::German},
{LanguageCode::IT, KeyboardLayout::Italian},
{LanguageCode::ES, KeyboardLayout::Spanish},
{LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified},
{LanguageCode::KO, KeyboardLayout::Korean},
{LanguageCode::NL, KeyboardLayout::EnglishUsInternational},
{LanguageCode::PT, KeyboardLayout::Portuguese},
{LanguageCode::RU, KeyboardLayout::Russian},
{LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional},
{LanguageCode::EN_GB, KeyboardLayout::EnglishUk},
{LanguageCode::FR_CA, KeyboardLayout::FrenchCa},
{LanguageCode::ES_419, KeyboardLayout::SpanishLatin},
{LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified},
{LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional},
{LanguageCode::PT_BR, KeyboardLayout::Portuguese},
}};
constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;

@ -32,6 +32,67 @@ enum class LanguageCode : u64 {
ZH_HANT = 0x00746E61482D687A, ZH_HANT = 0x00746E61482D687A,
PT_BR = 0x00000052422D7470, PT_BR = 0x00000052422D7470,
}; };
enum class KeyboardLayout : u64 {
Japanese = 0,
EnglishUs = 1,
EnglishUsInternational = 2,
EnglishUk = 3,
French = 4,
FrenchCa = 5,
Spanish = 6,
SpanishLatin = 7,
German = 8,
Italian = 9,
Portuguese = 10,
Russian = 11,
Korean = 12,
ChineseSimplified = 13,
ChineseTraditional = 14,
};
constexpr std::array<LanguageCode, 18> 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,
LanguageCode::PT_BR,
}};
static constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{
{LanguageCode::JA, KeyboardLayout::Japanese},
{LanguageCode::EN_US, KeyboardLayout::EnglishUs},
{LanguageCode::FR, KeyboardLayout::French},
{LanguageCode::DE, KeyboardLayout::German},
{LanguageCode::IT, KeyboardLayout::Italian},
{LanguageCode::ES, KeyboardLayout::Spanish},
{LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified},
{LanguageCode::KO, KeyboardLayout::Korean},
{LanguageCode::NL, KeyboardLayout::EnglishUsInternational},
{LanguageCode::PT, KeyboardLayout::Portuguese},
{LanguageCode::RU, KeyboardLayout::Russian},
{LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional},
{LanguageCode::EN_GB, KeyboardLayout::EnglishUk},
{LanguageCode::FR_CA, KeyboardLayout::FrenchCa},
{LanguageCode::ES_419, KeyboardLayout::SpanishLatin},
{LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified},
{LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional},
{LanguageCode::PT_BR, KeyboardLayout::Portuguese},
}};
LanguageCode GetLanguageCodeFromIndex(std::size_t idx); LanguageCode GetLanguageCodeFromIndex(std::size_t idx);
class SET final : public ServiceFramework<SET> { class SET final : public ServiceFramework<SET> {

@ -4,10 +4,12 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/string_util.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/system_archive/system_version.h" #include "core/file_sys/system_archive/system_version.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/set_sys.h" #include "core/hle/service/set/set_sys.h"
namespace Service::Set { namespace Service::Set {
@ -73,6 +75,16 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type)
} }
} // Anonymous namespace } // Anonymous namespace
void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
language_code_setting = rp.PopEnum<LanguageCode>();
LOG_INFO(Service_SET, "called, language_code={}", language_code_setting);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called"); LOG_DEBUG(Service_SET, "called");
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1); GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
@ -83,21 +95,113 @@ void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2); GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2);
} }
void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushRaw(account_settings);
}
void SET_SYS::SetAccountSettings(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
account_settings = rp.PopRaw<AccountSettings>();
LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetEulaVersions(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
ctx.WriteBuffer(eula_versions);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(eula_versions.size()));
}
void SET_SYS::SetEulaVersions(HLERequestContext& ctx) {
const auto elements = ctx.GetReadBufferNumElements<EulaVersion>();
const auto buffer_data = ctx.ReadBuffer();
LOG_INFO(Service_SET, "called, elements={}", elements);
eula_versions.resize(elements);
for (std::size_t index = 0; index < elements; index++) {
const std::size_t start_index = index * sizeof(EulaVersion);
memcpy(eula_versions.data() + start_index, buffer_data.data() + start_index,
sizeof(EulaVersion));
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetColorSetId(HLERequestContext& ctx) { void SET_SYS::GetColorSetId(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called"); LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushEnum(color_set); rb.PushEnum(color_set);
} }
void SET_SYS::SetColorSetId(HLERequestContext& ctx) { void SET_SYS::SetColorSetId(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
color_set = rp.PopEnum<ColorSet>(); color_set = rp.PopEnum<ColorSet>();
LOG_DEBUG(Service_SET, "called, color_set={}", color_set);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetNotificationSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 8};
rb.Push(ResultSuccess);
rb.PushRaw(notification_settings);
}
void SET_SYS::SetNotificationSettings(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
notification_settings = rp.PopRaw<NotificationSettings>();
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
notification_settings.flags.raw, notification_settings.volume,
notification_settings.start_time.hour, notification_settings.start_time.minute,
notification_settings.stop_time.hour, notification_settings.stop_time.minute);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetAccountNotificationSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
ctx.WriteBuffer(account_notifications);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(account_notifications.size()));
}
void SET_SYS::SetAccountNotificationSettings(HLERequestContext& ctx) {
const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>();
const auto buffer_data = ctx.ReadBuffer();
LOG_INFO(Service_SET, "called, elements={}", elements);
account_notifications.resize(elements);
for (std::size_t index = 0; index < elements; index++) {
const std::size_t start_index = index * sizeof(AccountNotificationSettings);
memcpy(account_notifications.data() + start_index, buffer_data.data() + start_index,
sizeof(AccountNotificationSettings));
}
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
@ -177,17 +281,218 @@ void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) {
rb.Push(response); rb.Push(response);
} }
void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) { void SET_SYS::GetTvSettings(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called"); LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(ResultSuccess);
rb.PushRaw(tv_settings);
}
void SET_SYS::SetTvSettings(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
tv_settings = rp.PopRaw<TvSettings>();
LOG_INFO(Service_SET,
"called, flags={}, cmu_mode={}, constrast_ratio={}, hdmi_content_type={}, "
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.constrast_ratio,
tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama,
tv_settings.tv_resolution, tv_settings.tv_underscan);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
}
void SET_SYS::GetQuestFlag(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(QuestFlag::Retail);
}
void SET_SYS::SetRegionCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
region_code = rp.PopEnum<RegionCode>();
LOG_INFO(Service_SET, "called, region_code={}", region_code);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetPrimaryAlbumStorage(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(PrimaryAlbumStorage::SdCard);
}
void SET_SYS::GetSleepSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 5};
rb.Push(ResultSuccess);
rb.PushRaw(sleep_settings);
}
void SET_SYS::SetSleepSettings(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
sleep_settings = rp.PopRaw<SleepSettings>();
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan,
sleep_settings.console_sleep_plan);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetInitialLaunchSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(ResultSuccess);
rb.PushRaw(launch_settings);
}
void SET_SYS::SetInitialLaunchSettings(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
launch_settings = rp.PopRaw<InitialLaunchSettings>();
LOG_INFO(Service_SET, "called, flags={}, timestamp={}", launch_settings.flags.raw,
launch_settings.timestamp.time_point);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
ctx.WriteBuffer(::Settings::values.device_name.GetValue()); ctx.WriteBuffer(::Settings::values.device_name.GetValue());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::SetDeviceNickName(HLERequestContext& ctx) {
const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer());
LOG_INFO(Service_SET, "called, device_name={}", device_name);
::Settings::values.device_name = device_name;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetProductModel(HLERequestContext& ctx) {
const u32 product_model = 1;
LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(product_model);
}
void SET_SYS::GetMiiAuthorId(HLERequestContext& ctx) {
const auto author_id = Common::UUID::MakeDefault();
LOG_WARNING(Service_SET, "(STUBBED) called, author_id={}", author_id.FormattedString());
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.PushRaw(author_id);
}
void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
u8 auto_update_flag{};
LOG_WARNING(Service_SET, "(STUBBED) called, auto_update_flag={}", auto_update_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(auto_update_flag);
}
void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) {
u8 battery_percentage_flag{1};
LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}",
battery_percentage_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(battery_percentage_flag);
}
void SET_SYS::GetErrorReportSharePermission(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(ErrorReportSharePermission::Denied);
}
void SET_SYS::GetAppletLaunchFlags(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(applet_launch_flag);
}
void SET_SYS::SetAppletLaunchFlags(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
applet_launch_flag = rp.Pop<u32>();
LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetKeyboardLayout(HLERequestContext& ctx) {
const auto language_code =
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
const auto key_code =
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
[=](const auto& element) { return element.first == language_code; });
KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
if (key_code != language_to_layout.end()) {
selected_keyboard_layout = key_code->second;
}
LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(selected_keyboard_layout));
}
void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(ChineseTraditionalInputMethod::Unknown0);
}
void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(false);
} }
SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "SetLanguageCode"}, {0, &SET_SYS::SetLanguageCode, "SetLanguageCode"},
{1, nullptr, "SetNetworkSettings"}, {1, nullptr, "SetNetworkSettings"},
{2, nullptr, "GetNetworkSettings"}, {2, nullptr, "GetNetworkSettings"},
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"}, {3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
@ -203,35 +508,35 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{14, nullptr, "SetExternalSteadyClockSourceId"}, {14, nullptr, "SetExternalSteadyClockSourceId"},
{15, nullptr, "GetUserSystemClockContext"}, {15, nullptr, "GetUserSystemClockContext"},
{16, nullptr, "SetUserSystemClockContext"}, {16, nullptr, "SetUserSystemClockContext"},
{17, nullptr, "GetAccountSettings"}, {17, &SET_SYS::GetAccountSettings, "GetAccountSettings"},
{18, nullptr, "SetAccountSettings"}, {18, &SET_SYS::SetAccountSettings, "SetAccountSettings"},
{19, nullptr, "GetAudioVolume"}, {19, nullptr, "GetAudioVolume"},
{20, nullptr, "SetAudioVolume"}, {20, nullptr, "SetAudioVolume"},
{21, nullptr, "GetEulaVersions"}, {21, &SET_SYS::GetEulaVersions, "GetEulaVersions"},
{22, nullptr, "SetEulaVersions"}, {22, &SET_SYS::SetEulaVersions, "SetEulaVersions"},
{23, &SET_SYS::GetColorSetId, "GetColorSetId"}, {23, &SET_SYS::GetColorSetId, "GetColorSetId"},
{24, &SET_SYS::SetColorSetId, "SetColorSetId"}, {24, &SET_SYS::SetColorSetId, "SetColorSetId"},
{25, nullptr, "GetConsoleInformationUploadFlag"}, {25, nullptr, "GetConsoleInformationUploadFlag"},
{26, nullptr, "SetConsoleInformationUploadFlag"}, {26, nullptr, "SetConsoleInformationUploadFlag"},
{27, nullptr, "GetAutomaticApplicationDownloadFlag"}, {27, nullptr, "GetAutomaticApplicationDownloadFlag"},
{28, nullptr, "SetAutomaticApplicationDownloadFlag"}, {28, nullptr, "SetAutomaticApplicationDownloadFlag"},
{29, nullptr, "GetNotificationSettings"}, {29, &SET_SYS::GetNotificationSettings, "GetNotificationSettings"},
{30, nullptr, "SetNotificationSettings"}, {30, &SET_SYS::SetNotificationSettings, "SetNotificationSettings"},
{31, nullptr, "GetAccountNotificationSettings"}, {31, &SET_SYS::GetAccountNotificationSettings, "GetAccountNotificationSettings"},
{32, nullptr, "SetAccountNotificationSettings"}, {32, &SET_SYS::SetAccountNotificationSettings, "SetAccountNotificationSettings"},
{35, nullptr, "GetVibrationMasterVolume"}, {35, nullptr, "GetVibrationMasterVolume"},
{36, nullptr, "SetVibrationMasterVolume"}, {36, nullptr, "SetVibrationMasterVolume"},
{37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
{38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"}, {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"},
{39, nullptr, "GetTvSettings"}, {39, &SET_SYS::GetTvSettings, "GetTvSettings"},
{40, nullptr, "SetTvSettings"}, {40, &SET_SYS::SetTvSettings, "SetTvSettings"},
{41, nullptr, "GetEdid"}, {41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"}, {42, nullptr, "SetEdid"},
{43, nullptr, "GetAudioOutputMode"}, {43, nullptr, "GetAudioOutputMode"},
{44, nullptr, "SetAudioOutputMode"}, {44, nullptr, "SetAudioOutputMode"},
{45, nullptr, "IsForceMuteOnHeadphoneRemoved"}, {45, nullptr, "IsForceMuteOnHeadphoneRemoved"},
{46, nullptr, "SetForceMuteOnHeadphoneRemoved"}, {46, nullptr, "SetForceMuteOnHeadphoneRemoved"},
{47, nullptr, "GetQuestFlag"}, {47, &SET_SYS::GetQuestFlag, "GetQuestFlag"},
{48, nullptr, "SetQuestFlag"}, {48, nullptr, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"}, {49, nullptr, "GetDataDeletionSettings"},
{50, nullptr, "SetDataDeletionSettings"}, {50, nullptr, "SetDataDeletionSettings"},
@ -241,13 +546,13 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{54, nullptr, "SetDeviceTimeZoneLocationName"}, {54, nullptr, "SetDeviceTimeZoneLocationName"},
{55, nullptr, "GetWirelessCertificationFileSize"}, {55, nullptr, "GetWirelessCertificationFileSize"},
{56, nullptr, "GetWirelessCertificationFile"}, {56, nullptr, "GetWirelessCertificationFile"},
{57, nullptr, "SetRegionCode"}, {57, &SET_SYS::SetRegionCode, "SetRegionCode"},
{58, nullptr, "GetNetworkSystemClockContext"}, {58, nullptr, "GetNetworkSystemClockContext"},
{59, nullptr, "SetNetworkSystemClockContext"}, {59, nullptr, "SetNetworkSystemClockContext"},
{60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"}, {60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"},
{61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"}, {61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"},
{62, nullptr, "GetDebugModeFlag"}, {62, nullptr, "GetDebugModeFlag"},
{63, nullptr, "GetPrimaryAlbumStorage"}, {63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
{64, nullptr, "SetPrimaryAlbumStorage"}, {64, nullptr, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"}, {65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"}, {66, nullptr, "SetUsb30EnableFlag"},
@ -255,15 +560,15 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{68, nullptr, "GetSerialNumber"}, {68, nullptr, "GetSerialNumber"},
{69, nullptr, "GetNfcEnableFlag"}, {69, nullptr, "GetNfcEnableFlag"},
{70, nullptr, "SetNfcEnableFlag"}, {70, nullptr, "SetNfcEnableFlag"},
{71, nullptr, "GetSleepSettings"}, {71, &SET_SYS::GetSleepSettings, "GetSleepSettings"},
{72, nullptr, "SetSleepSettings"}, {72, &SET_SYS::SetSleepSettings, "SetSleepSettings"},
{73, nullptr, "GetWirelessLanEnableFlag"}, {73, nullptr, "GetWirelessLanEnableFlag"},
{74, nullptr, "SetWirelessLanEnableFlag"}, {74, nullptr, "SetWirelessLanEnableFlag"},
{75, nullptr, "GetInitialLaunchSettings"}, {75, &SET_SYS::GetInitialLaunchSettings, "GetInitialLaunchSettings"},
{76, nullptr, "SetInitialLaunchSettings"}, {76, &SET_SYS::SetInitialLaunchSettings, "SetInitialLaunchSettings"},
{77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"}, {77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"},
{78, nullptr, "SetDeviceNickName"}, {78, &SET_SYS::SetDeviceNickName, "SetDeviceNickName"},
{79, nullptr, "GetProductModel"}, {79, &SET_SYS::GetProductModel, "GetProductModel"},
{80, nullptr, "GetLdnChannel"}, {80, nullptr, "GetLdnChannel"},
{81, nullptr, "SetLdnChannel"}, {81, nullptr, "SetLdnChannel"},
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
@ -274,16 +579,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{87, nullptr, "SetPtmFuelGaugeParameter"}, {87, nullptr, "SetPtmFuelGaugeParameter"},
{88, nullptr, "GetBluetoothEnableFlag"}, {88, nullptr, "GetBluetoothEnableFlag"},
{89, nullptr, "SetBluetoothEnableFlag"}, {89, nullptr, "SetBluetoothEnableFlag"},
{90, nullptr, "GetMiiAuthorId"}, {90, &SET_SYS::GetMiiAuthorId, "GetMiiAuthorId"},
{91, nullptr, "SetShutdownRtcValue"}, {91, nullptr, "SetShutdownRtcValue"},
{92, nullptr, "GetShutdownRtcValue"}, {92, nullptr, "GetShutdownRtcValue"},
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, {93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"}, {94, nullptr, "GetFatalDirtyFlags"},
{95, nullptr, "GetAutoUpdateEnableFlag"}, {95, &SET_SYS::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
{96, nullptr, "SetAutoUpdateEnableFlag"}, {96, nullptr, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"}, {97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"}, {98, nullptr, "SetNxControllerSettings"},
{99, nullptr, "GetBatteryPercentageFlag"}, {99, &SET_SYS::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
{100, nullptr, "SetBatteryPercentageFlag"}, {100, nullptr, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"}, {101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"}, {102, nullptr, "SetExternalRtcResetFlag"},
@ -308,10 +613,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{121, nullptr, "SetPushNotificationActivityModeOnSleep"}, {121, nullptr, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"}, {122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"}, {123, nullptr, "SetServiceDiscoveryControlSettings"},
{124, nullptr, "GetErrorReportSharePermission"}, {124, &SET_SYS::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
{125, nullptr, "SetErrorReportSharePermission"}, {125, nullptr, "SetErrorReportSharePermission"},
{126, nullptr, "GetAppletLaunchFlags"}, {126, &SET_SYS::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
{127, nullptr, "SetAppletLaunchFlags"}, {127, &SET_SYS::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
@ -320,7 +625,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
{136, nullptr, "GetKeyboardLayout"}, {136, &SET_SYS::GetKeyboardLayout, "GetKeyboardLayout"},
{137, nullptr, "SetKeyboardLayout"}, {137, nullptr, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"}, {138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"}, {139, nullptr, "GetAllowedSslHosts"},
@ -354,7 +659,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{167, nullptr, "SetUsb30DeviceEnableFlag"}, {167, nullptr, "SetUsb30DeviceEnableFlag"},
{168, nullptr, "GetThemeId"}, {168, nullptr, "GetThemeId"},
{169, nullptr, "SetThemeId"}, {169, nullptr, "SetThemeId"},
{170, nullptr, "GetChineseTraditionalInputMethod"}, {170, &SET_SYS::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"},
{171, nullptr, "SetChineseTraditionalInputMethod"}, {171, nullptr, "SetChineseTraditionalInputMethod"},
{172, nullptr, "GetPtmCycleCountReliability"}, {172, nullptr, "GetPtmCycleCountReliability"},
{173, nullptr, "SetPtmCycleCountReliability"}, {173, nullptr, "SetPtmCycleCountReliability"},
@ -385,12 +690,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
{199, nullptr, "GetButtonConfigRegisteredSettings"}, {199, nullptr, "GetButtonConfigRegisteredSettings"},
{200, nullptr, "SetButtonConfigRegisteredSettings"}, {200, nullptr, "SetButtonConfigRegisteredSettings"},
{201, nullptr, "GetFieldTestingFlag"}, {201, &SET_SYS::GetFieldTestingFlag, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"}, {202, nullptr, "SetFieldTestingFlag"},
{203, nullptr, "GetPanelCrcMode"}, {203, nullptr, "GetPanelCrcMode"},
{204, nullptr, "SetPanelCrcMode"}, {204, nullptr, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"}, {205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"}, {206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
{208, nullptr, "SetHearingProtectionSafeguardFlag"},
{209, nullptr, "GetHearingProtectionSafeguardRemainingTime"},
{210, nullptr, "SetHearingProtectionSafeguardRemainingTime"},
}; };
// clang-format on // clang-format on

@ -3,7 +3,9 @@
#pragma once #pragma once
#include "common/uuid.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/time/clock_types.h"
namespace Core { namespace Core {
class System; class System;
@ -23,15 +25,331 @@ private:
BasicBlack = 1, BasicBlack = 1,
}; };
void GetSettingsItemValueSize(HLERequestContext& ctx); /// Indicates the current console is a retail or kiosk unit
void GetSettingsItemValue(HLERequestContext& ctx); enum class QuestFlag : u8 {
Retail = 0,
Kiosk = 1,
};
/// This is nn::settings::system::TvResolution
enum class TvResolution : u32 {
Auto,
Resolution1080p,
Resolution720p,
Resolution480p,
};
/// This is nn::settings::system::HdmiContentType
enum class HdmiContentType : u32 {
None,
Graphics,
Cinema,
Photo,
Game,
};
/// This is nn::settings::system::RgbRange
enum class RgbRange : u32 {
Auto,
Full,
Limited,
};
/// This is nn::settings::system::CmuMode
enum class CmuMode : u32 {
None,
ColorInvert,
HighContrast,
GrayScale,
};
/// This is nn::settings::system::PrimaryAlbumStorage
enum class PrimaryAlbumStorage : u32 {
Nand,
SdCard,
};
/// This is nn::settings::system::NotificationVolume
enum class NotificationVolume : u32 {
Mute,
Low,
High,
};
/// This is nn::settings::system::ChineseTraditionalInputMethod
enum class ChineseTraditionalInputMethod : u32 {
Unknown0 = 0,
Unknown1 = 1,
Unknown2 = 2,
};
/// This is nn::settings::system::ErrorReportSharePermission
enum class ErrorReportSharePermission : u32 {
NotConfirmed,
Granted,
Denied,
};
/// This is nn::settings::system::FriendPresenceOverlayPermission
enum class FriendPresenceOverlayPermission : u8 {
NotConfirmed,
NoDisplay,
FavoriteFriends,
Friends,
};
/// This is nn::settings::system::HandheldSleepPlan
enum class HandheldSleepPlan : u32 {
Sleep1Min,
Sleep3Min,
Sleep5Min,
Sleep10Min,
Sleep30Min,
Never,
};
/// This is nn::settings::system::ConsoleSleepPlan
enum class ConsoleSleepPlan : u32 {
Sleep1Hour,
Sleep2Hour,
Sleep3Hour,
Sleep6Hour,
Sleep12Hour,
Never,
};
/// This is nn::settings::system::RegionCode
enum class RegionCode : u32 {
Japan,
Usa,
Europe,
Australia,
HongKongTaiwanKorea,
China,
};
/// This is nn::settings::system::EulaVersionClockType
enum class EulaVersionClockType : u32 {
NetworkSystemClock,
SteadyClock,
};
/// This is nn::settings::system::SleepFlag
struct SleepFlag {
union {
u32 raw{};
BitField<0, 1, u32> SleepsWhilePlayingMedia;
BitField<1, 1, u32> WakesAtPowerStateChange;
};
};
static_assert(sizeof(SleepFlag) == 4, "TvFlag is an invalid size");
/// This is nn::settings::system::TvFlag
struct TvFlag {
union {
u32 raw{};
BitField<0, 1, u32> Allows4k;
BitField<1, 1, u32> Allows3d;
BitField<2, 1, u32> AllowsCec;
BitField<3, 1, u32> PreventsScreenBurnIn;
};
};
static_assert(sizeof(TvFlag) == 4, "TvFlag is an invalid size");
/// This is nn::settings::system::InitialLaunchFlag
struct InitialLaunchFlag {
union {
u32 raw{};
BitField<0, 1, u32> InitialLaunchCompletionFlag;
BitField<8, 1, u32> InitialLaunchUserAdditionFlag;
BitField<16, 1, u32> InitialLaunchTimestampFlag;
};
};
static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size");
/// This is nn::settings::system::NotificationFlag
struct NotificationFlag {
union {
u32 raw{};
BitField<0, 1, u32> RingtoneFlag;
BitField<1, 1, u32> DownloadCompletionFlag;
BitField<8, 1, u32> EnablesNews;
BitField<9, 1, u32> IncomingLampFlag;
};
};
static_assert(sizeof(NotificationFlag) == 4, "NotificationFlag is an invalid size");
/// This is nn::settings::system::AccountNotificationFlag
struct AccountNotificationFlag {
union {
u32 raw{};
BitField<0, 1, u32> FriendOnlineFlag;
BitField<1, 1, u32> FriendRequestFlag;
BitField<8, 1, u32> CoralInvitationFlag;
};
};
static_assert(sizeof(AccountNotificationFlag) == 4,
"AccountNotificationFlag is an invalid size");
/// This is nn::settings::system::TvSettings
struct TvSettings {
TvFlag flags;
TvResolution tv_resolution;
HdmiContentType hdmi_content_type;
RgbRange rgb_range;
CmuMode cmu_mode;
u32 tv_underscan;
f32 tv_gama;
f32 constrast_ratio;
};
static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size");
/// This is nn::settings::system::NotificationTime
struct NotificationTime {
u32 hour;
u32 minute;
};
static_assert(sizeof(NotificationTime) == 0x8, "NotificationTime is an invalid size");
/// This is nn::settings::system::NotificationSettings
struct NotificationSettings {
NotificationFlag flags;
NotificationVolume volume;
NotificationTime start_time;
NotificationTime stop_time;
};
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
/// This is nn::settings::system::AccountSettings
struct AccountSettings {
u32 flags;
};
static_assert(sizeof(AccountSettings) == 0x4, "AccountSettings is an invalid size");
/// This is nn::settings::system::AccountNotificationSettings
struct AccountNotificationSettings {
Common::UUID uid;
AccountNotificationFlag flags;
FriendPresenceOverlayPermission friend_presence_permission;
FriendPresenceOverlayPermission friend_invitation_permission;
INSERT_PADDING_BYTES(0x2);
};
static_assert(sizeof(AccountNotificationSettings) == 0x18,
"AccountNotificationSettings is an invalid size");
/// This is nn::settings::system::InitialLaunchSettings
struct SleepSettings {
SleepFlag flags;
HandheldSleepPlan handheld_sleep_plan;
ConsoleSleepPlan console_sleep_plan;
};
static_assert(sizeof(SleepSettings) == 0xc, "SleepSettings is incorrect size");
/// This is nn::settings::system::InitialLaunchSettings
struct InitialLaunchSettings {
InitialLaunchFlag flags;
INSERT_PADDING_BYTES(0x4);
Time::Clock::SteadyClockTimePoint timestamp;
};
static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size");
/// This is nn::settings::system::InitialLaunchSettings
struct EulaVersion {
u32 version;
RegionCode region_code;
EulaVersionClockType clock_type;
INSERT_PADDING_BYTES(0x4);
s64 posix_time;
Time::Clock::SteadyClockTimePoint timestamp;
};
static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
void SetLanguageCode(HLERequestContext& ctx);
void GetFirmwareVersion(HLERequestContext& ctx); void GetFirmwareVersion(HLERequestContext& ctx);
void GetFirmwareVersion2(HLERequestContext& ctx); void GetFirmwareVersion2(HLERequestContext& ctx);
void GetAccountSettings(HLERequestContext& ctx);
void SetAccountSettings(HLERequestContext& ctx);
void GetEulaVersions(HLERequestContext& ctx);
void SetEulaVersions(HLERequestContext& ctx);
void GetColorSetId(HLERequestContext& ctx); void GetColorSetId(HLERequestContext& ctx);
void SetColorSetId(HLERequestContext& ctx); void SetColorSetId(HLERequestContext& ctx);
void GetNotificationSettings(HLERequestContext& ctx);
void SetNotificationSettings(HLERequestContext& ctx);
void GetAccountNotificationSettings(HLERequestContext& ctx);
void SetAccountNotificationSettings(HLERequestContext& ctx);
void GetSettingsItemValueSize(HLERequestContext& ctx);
void GetSettingsItemValue(HLERequestContext& ctx);
void GetTvSettings(HLERequestContext& ctx);
void SetTvSettings(HLERequestContext& ctx);
void GetQuestFlag(HLERequestContext& ctx);
void SetRegionCode(HLERequestContext& ctx);
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
void GetSleepSettings(HLERequestContext& ctx);
void SetSleepSettings(HLERequestContext& ctx);
void GetInitialLaunchSettings(HLERequestContext& ctx);
void SetInitialLaunchSettings(HLERequestContext& ctx);
void GetDeviceNickName(HLERequestContext& ctx); void GetDeviceNickName(HLERequestContext& ctx);
void SetDeviceNickName(HLERequestContext& ctx);
void GetProductModel(HLERequestContext& ctx);
void GetMiiAuthorId(HLERequestContext& ctx);
void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
void GetBatteryPercentageFlag(HLERequestContext& ctx);
void GetErrorReportSharePermission(HLERequestContext& ctx);
void GetAppletLaunchFlags(HLERequestContext& ctx);
void SetAppletLaunchFlags(HLERequestContext& ctx);
void GetKeyboardLayout(HLERequestContext& ctx);
void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
void GetFieldTestingFlag(HLERequestContext& ctx);
AccountSettings account_settings{
.flags = {},
};
ColorSet color_set = ColorSet::BasicWhite; ColorSet color_set = ColorSet::BasicWhite;
NotificationSettings notification_settings{
.flags = {0x300},
.volume = NotificationVolume::High,
.start_time = {.hour = 9, .minute = 0},
.stop_time = {.hour = 21, .minute = 0},
};
std::vector<AccountNotificationSettings> account_notifications{};
TvSettings tv_settings{
.flags = {0xc},
.tv_resolution = TvResolution::Auto,
.hdmi_content_type = HdmiContentType::Game,
.rgb_range = RgbRange::Auto,
.cmu_mode = CmuMode::None,
.tv_underscan = {},
.tv_gama = 1.0f,
.constrast_ratio = 0.5f,
};
InitialLaunchSettings launch_settings{
.flags = {0x10001},
.timestamp = {},
};
SleepSettings sleep_settings{
.flags = {0x3},
.handheld_sleep_plan = HandheldSleepPlan::Sleep10Min,
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
};
u32 applet_launch_flag{};
std::vector<EulaVersion> eula_versions{};
RegionCode region_code;
LanguageCode language_code_setting;
}; };
} // namespace Service::Set } // namespace Service::Set