Merge pull request #10603 from lat9nq/tz-more-complete
core,common: Implement missing time zone data/computations
This commit is contained in:
commit
698a3eda50
19 changed files with 550 additions and 710 deletions
|
@ -22,10 +22,6 @@ s64 GetSecondsSinceEpoch() {
|
|||
return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() +
|
||||
Settings::values.custom_rtc_differential;
|
||||
}
|
||||
|
||||
s64 GetExternalRtcValue() {
|
||||
return GetSecondsSinceEpoch() + TimeManager::GetExternalTimeZoneOffset();
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
struct TimeManager::Impl final {
|
||||
|
@ -43,7 +39,7 @@ struct TimeManager::Impl final {
|
|||
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
|
||||
time_zone_content_manager{system} {
|
||||
|
||||
const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
|
||||
const auto system_time{Clock::TimeSpanType::FromSeconds(GetSecondsSinceEpoch())};
|
||||
SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {});
|
||||
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
|
||||
|
||||
|
@ -107,7 +103,7 @@ struct TimeManager::Impl final {
|
|||
|
||||
void SetupTimeZoneManager(std::string location_name,
|
||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
||||
std::size_t total_location_name_count, u128 time_zone_rule_version,
|
||||
std::vector<std::string> location_names, u128 time_zone_rule_version,
|
||||
FileSys::VirtualFile& vfs_file) {
|
||||
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
|
||||
location_name, vfs_file) != ResultSuccess) {
|
||||
|
@ -117,20 +113,13 @@ struct TimeManager::Impl final {
|
|||
|
||||
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
|
||||
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
|
||||
total_location_name_count);
|
||||
location_names.size());
|
||||
time_zone_content_manager.GetTimeZoneManager().SetLocationNames(location_names);
|
||||
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
|
||||
time_zone_rule_version);
|
||||
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
|
||||
}
|
||||
|
||||
static s64 GetExternalTimeZoneOffset() {
|
||||
// With "auto" timezone setting, we use the external system's timezone offset
|
||||
if (Settings::GetTimeZoneString() == "auto") {
|
||||
return Common::TimeZone::GetCurrentOffsetSeconds().count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id,
|
||||
Clock::TimeSpanType setup_value,
|
||||
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
|
||||
|
@ -295,19 +284,10 @@ void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
|
|||
|
||||
void TimeManager::SetupTimeZoneManager(std::string location_name,
|
||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
||||
std::size_t total_location_name_count,
|
||||
std::vector<std::string> location_names,
|
||||
u128 time_zone_rule_version,
|
||||
FileSys::VirtualFile& vfs_file) {
|
||||
impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point,
|
||||
total_location_name_count, time_zone_rule_version, vfs_file);
|
||||
impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, location_names,
|
||||
time_zone_rule_version, vfs_file);
|
||||
}
|
||||
|
||||
/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() {
|
||||
// With "auto" timezone setting, we use the external system's timezone offset
|
||||
if (Settings::GetTimeZoneString() == "auto") {
|
||||
return Common::TimeZone::GetCurrentOffsetSeconds().count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
|
|
|
@ -61,11 +61,9 @@ public:
|
|||
|
||||
void SetupTimeZoneManager(std::string location_name,
|
||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
||||
std::size_t total_location_name_count, u128 time_zone_rule_version,
|
||||
std::vector<std::string> location_names, u128 time_zone_rule_version,
|
||||
FileSys::VirtualFile& vfs_file);
|
||||
|
||||
static s64 GetExternalTimeZoneOffset();
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
|
@ -12,7 +13,11 @@
|
|||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/time/errors.h"
|
||||
#include "core/hle/service/time/time_manager.h"
|
||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
||||
|
||||
|
@ -71,19 +76,13 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
|
|||
: system{system_}, location_name_cache{BuildLocationNameCache(system)} {}
|
||||
|
||||
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
|
||||
std::string location_name;
|
||||
const auto timezone_setting = Settings::GetTimeZoneString();
|
||||
if (timezone_setting == "auto" || timezone_setting == "default") {
|
||||
location_name = Common::TimeZone::GetDefaultTimeZone();
|
||||
} else {
|
||||
location_name = timezone_setting;
|
||||
}
|
||||
|
||||
if (FileSys::VirtualFile vfs_file;
|
||||
GetTimeZoneInfoFile(location_name, vfs_file) == ResultSuccess) {
|
||||
GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
|
||||
const auto time_point{
|
||||
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
|
||||
time_manager.SetupTimeZoneManager(location_name, time_point, location_name_cache.size(), {},
|
||||
time_manager.SetupTimeZoneManager(timezone_setting, time_point, location_name_cache, {},
|
||||
vfs_file);
|
||||
} else {
|
||||
time_zone_manager.MarkAsInitialized();
|
||||
|
@ -126,8 +125,15 @@ Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_n
|
|||
|
||||
vfs_file = zoneinfo_dir->GetFileRelative(location_name);
|
||||
if (!vfs_file) {
|
||||
LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
|
||||
time_zone_binary_titleid, location_name);
|
||||
LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using system timezone.",
|
||||
time_zone_binary_titleid, location_name);
|
||||
const std::string system_time_zone{Common::TimeZone::FindSystemTimeZone()};
|
||||
vfs_file = zoneinfo_dir->GetFile(system_time_zone);
|
||||
}
|
||||
|
||||
if (!vfs_file) {
|
||||
LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
|
||||
time_zone_binary_titleid, location_name);
|
||||
vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
|
@ -9,6 +10,7 @@
|
|||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/service/time/time_zone_manager.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
|
@ -128,10 +130,10 @@ static constexpr int GetQZName(const char* name, int offset, char delimiter) {
|
|||
}
|
||||
|
||||
static constexpr int GetTZName(const char* name, int offset) {
|
||||
for (char value{name[offset]};
|
||||
value != '\0' && !IsDigit(value) && value != ',' && value != '-' && value != '+';
|
||||
offset++) {
|
||||
value = name[offset];
|
||||
char c;
|
||||
|
||||
while ((c = name[offset]) != '\0' && !IsDigit(c) && c != ',' && c != '-' && c != '+') {
|
||||
++offset;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
@ -147,6 +149,7 @@ static constexpr bool GetInteger(const char* name, int& offset, int& value, int
|
|||
if (value > max) {
|
||||
return {};
|
||||
}
|
||||
offset++;
|
||||
temp = name[offset];
|
||||
} while (IsDigit(temp));
|
||||
|
||||
|
@ -471,6 +474,13 @@ static bool ParsePosixName(const char* name, TimeZoneRule& rule) {
|
|||
their_std_offset = their_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule.time_count > 0) {
|
||||
UNIMPLEMENTED();
|
||||
// TODO (lat9nq): Implement eggert/tz/localtime.c:tzparse:1329
|
||||
// Seems to be unused in yuzu for now: I never hit the UNIMPLEMENTED in testing
|
||||
}
|
||||
|
||||
rule.ttis[0].gmt_offset = -std_offset;
|
||||
rule.ttis[0].is_dst = false;
|
||||
rule.ttis[0].abbreviation_list_index = 0;
|
||||
|
@ -514,6 +524,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
|
|||
|
||||
constexpr s32 time_zone_max_leaps{50};
|
||||
constexpr s32 time_zone_max_chars{50};
|
||||
constexpr s32 time_zone_max_times{1000};
|
||||
if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps &&
|
||||
0 < header.type_count && header.type_count < s32(time_zone_rule.ttis.size()) &&
|
||||
0 <= header.time_count && header.time_count < s32(time_zone_rule.ats.size()) &&
|
||||
|
@ -546,7 +557,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
|
|||
for (int index{}; index < time_zone_rule.time_count; ++index) {
|
||||
const u8 type{*vfs_file->ReadByte(read_offset)};
|
||||
read_offset += sizeof(u8);
|
||||
if (time_zone_rule.time_count <= type) {
|
||||
if (time_zone_rule.type_count <= type) {
|
||||
return {};
|
||||
}
|
||||
if (time_zone_rule.types[index] != 0) {
|
||||
|
@ -624,16 +635,109 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
|
|||
std::array<char, time_zone_name_max> name{};
|
||||
std::memcpy(name.data(), temp_name.data() + 1, std::size_t(bytes_read - 1));
|
||||
|
||||
// Fill in computed transition times with temp rule
|
||||
TimeZoneRule temp_rule;
|
||||
if (ParsePosixName(name.data(), temp_rule)) {
|
||||
UNIMPLEMENTED();
|
||||
int have_abbreviation = 0;
|
||||
int char_count = time_zone_rule.char_count;
|
||||
|
||||
for (int i = 0; i < temp_rule.type_count; i++) {
|
||||
char* temp_abbreviation =
|
||||
temp_rule.chars.data() + temp_rule.ttis[i].abbreviation_list_index;
|
||||
int j;
|
||||
for (j = 0; j < char_count; j++) {
|
||||
if (std::strcmp(time_zone_rule.chars.data() + j, temp_abbreviation) == 0) {
|
||||
temp_rule.ttis[i].abbreviation_list_index = j;
|
||||
have_abbreviation++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j >= char_count) {
|
||||
int temp_abbreviation_length = static_cast<int>(std::strlen(temp_abbreviation));
|
||||
if (j + temp_abbreviation_length < time_zone_max_chars) {
|
||||
std::strcpy(time_zone_rule.chars.data() + j, temp_abbreviation);
|
||||
char_count = j + temp_abbreviation_length + 1;
|
||||
temp_rule.ttis[i].abbreviation_list_index = j;
|
||||
have_abbreviation++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (have_abbreviation == temp_rule.type_count) {
|
||||
time_zone_rule.char_count = char_count;
|
||||
|
||||
// Original comment:
|
||||
/* Ignore any trailing, no-op transitions generated
|
||||
by zic as they don't help here and can run afoul
|
||||
of bugs in zic 2016j or earlier. */
|
||||
// This is possibly unnecessary for yuzu, since Nintendo doesn't run zic
|
||||
while (1 < time_zone_rule.time_count &&
|
||||
(time_zone_rule.types[time_zone_rule.time_count - 1] ==
|
||||
time_zone_rule.types[time_zone_rule.time_count - 2])) {
|
||||
time_zone_rule.time_count--;
|
||||
}
|
||||
|
||||
for (int i = 0;
|
||||
i < temp_rule.time_count && time_zone_rule.time_count < time_zone_max_times;
|
||||
i++) {
|
||||
const s64 transition_time = temp_rule.ats[i];
|
||||
if (0 < time_zone_rule.time_count &&
|
||||
transition_time <= time_zone_rule.ats[time_zone_rule.time_count - 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
time_zone_rule.ats[time_zone_rule.time_count] = transition_time;
|
||||
time_zone_rule.types[time_zone_rule.time_count] =
|
||||
static_cast<s8>(time_zone_rule.type_count + temp_rule.types[i]);
|
||||
time_zone_rule.time_count++;
|
||||
}
|
||||
for (int i = 0; i < temp_rule.type_count; i++) {
|
||||
time_zone_rule.ttis[time_zone_rule.type_count++] = temp_rule.ttis[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool {
|
||||
if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const struct TimeTypeInfo* ap = &rule.ttis[a];
|
||||
const struct TimeTypeInfo* bp = &rule.ttis[b];
|
||||
|
||||
return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst &&
|
||||
(std::strcmp(&rule.chars[ap->abbreviation_list_index],
|
||||
&rule.chars[bp->abbreviation_list_index]) == 0));
|
||||
};
|
||||
|
||||
if (time_zone_rule.type_count == 0) {
|
||||
return {};
|
||||
}
|
||||
if (time_zone_rule.time_count > 1) {
|
||||
UNIMPLEMENTED();
|
||||
if (time_zone_rule.ats[0] <= std::numeric_limits<s64>::max() - seconds_per_repeat) {
|
||||
s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat;
|
||||
int repeatattype = time_zone_rule.types[0];
|
||||
for (int i = 1; i < time_zone_rule.time_count; ++i) {
|
||||
if (time_zone_rule.ats[i] == repeatat &&
|
||||
typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
|
||||
time_zone_rule.go_back = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (std::numeric_limits<s64>::min() + seconds_per_repeat <=
|
||||
time_zone_rule.ats[time_zone_rule.time_count - 1]) {
|
||||
s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat;
|
||||
int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1];
|
||||
for (int i = time_zone_rule.time_count; i >= 0; --i) {
|
||||
if (time_zone_rule.ats[i] == repeatat &&
|
||||
typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
|
||||
time_zone_rule.go_ahead = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 default_type{};
|
||||
|
@ -1038,4 +1142,36 @@ Result TimeZoneManager::GetDeviceLocationName(LocationName& value) const {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result TimeZoneManager::GetTotalLocationNameCount(s32& count) const {
|
||||
if (!is_initialized) {
|
||||
return ERROR_UNINITIALIZED_CLOCK;
|
||||
}
|
||||
count = static_cast<u32>(total_location_name_count);
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result TimeZoneManager::GetTimeZoneRuleVersion(u128& version) const {
|
||||
if (!is_initialized) {
|
||||
return ERROR_UNINITIALIZED_CLOCK;
|
||||
}
|
||||
version = time_zone_rule_version;
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result TimeZoneManager::LoadLocationNameList(std::vector<LocationName>& values) const {
|
||||
if (!is_initialized) {
|
||||
return ERROR_UNINITIALIZED_CLOCK;
|
||||
}
|
||||
|
||||
for (const auto& name : total_location_names) {
|
||||
LocationName entry{};
|
||||
std::memcpy(entry.data(), name.c_str(), name.size());
|
||||
values.push_back(entry);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
} // namespace Service::Time::TimeZone
|
||||
|
|
|
@ -21,6 +21,10 @@ public:
|
|||
total_location_name_count = value;
|
||||
}
|
||||
|
||||
void SetLocationNames(std::vector<std::string> location_names) {
|
||||
total_location_names = location_names;
|
||||
}
|
||||
|
||||
void SetTimeZoneRuleVersion(const u128& value) {
|
||||
time_zone_rule_version = value;
|
||||
}
|
||||
|
@ -33,6 +37,9 @@ public:
|
|||
FileSys::VirtualFile& vfs_file);
|
||||
Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
|
||||
Result GetDeviceLocationName(TimeZone::LocationName& value) const;
|
||||
Result GetTotalLocationNameCount(s32& count) const;
|
||||
Result GetTimeZoneRuleVersion(u128& version) const;
|
||||
Result LoadLocationNameList(std::vector<TimeZone::LocationName>& values) const;
|
||||
Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
|
||||
Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
|
||||
Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
|
||||
|
@ -46,6 +53,7 @@ private:
|
|||
std::string device_location_name{"GMT"};
|
||||
u128 time_zone_rule_version{};
|
||||
std::size_t total_location_name_count{};
|
||||
std::vector<std::string> total_location_names{};
|
||||
Clock::SteadyClockTimePoint time_zone_update_time_point{
|
||||
Clock::SteadyClockTimePoint::GetRandom()};
|
||||
};
|
||||
|
|
|
@ -15,10 +15,10 @@ ITimeZoneService::ITimeZoneService(Core::System& system_,
|
|||
static const FunctionInfo functions[] = {
|
||||
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, nullptr, "SetDeviceLocationName"},
|
||||
{2, nullptr, "GetTotalLocationNameCount"},
|
||||
{3, nullptr, "LoadLocationNameList"},
|
||||
{2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||
{3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"},
|
||||
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, nullptr, "GetTimeZoneRuleVersion"},
|
||||
{5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
||||
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
|
@ -45,6 +45,57 @@ void ITimeZoneService::GetDeviceLocationName(HLERequestContext& ctx) {
|
|||
rb.PushRaw(location_name);
|
||||
}
|
||||
|
||||
void ITimeZoneService::GetTotalLocationNameCount(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
s32 count{};
|
||||
if (const Result result{
|
||||
time_zone_content_manager.GetTimeZoneManager().GetTotalLocationNameCount(count)};
|
||||
result != ResultSuccess) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void ITimeZoneService::LoadLocationNameList(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
std::vector<TimeZone::LocationName> location_names{};
|
||||
if (const Result result{
|
||||
time_zone_content_manager.GetTimeZoneManager().LoadLocationNameList(location_names)};
|
||||
result != ResultSuccess) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(location_names);
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<s32>(location_names.size()));
|
||||
}
|
||||
void ITimeZoneService::GetTimeZoneRuleVersion(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
u128 rule_version{};
|
||||
if (const Result result{
|
||||
time_zone_content_manager.GetTimeZoneManager().GetTimeZoneRuleVersion(rule_version)};
|
||||
result != ResultSuccess) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(rule_version);
|
||||
}
|
||||
|
||||
void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
|
||||
|
|
|
@ -22,6 +22,9 @@ public:
|
|||
|
||||
private:
|
||||
void GetDeviceLocationName(HLERequestContext& ctx);
|
||||
void GetTotalLocationNameCount(HLERequestContext& ctx);
|
||||
void LoadLocationNameList(HLERequestContext& ctx);
|
||||
void GetTimeZoneRuleVersion(HLERequestContext& ctx);
|
||||
void LoadTimeZoneRule(HLERequestContext& ctx);
|
||||
void ToCalendarTime(HLERequestContext& ctx);
|
||||
void ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue