summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar bunnei2023-06-13 13:28:45 -0700
committerGravatar GitHub2023-06-13 13:28:45 -0700
commit698a3eda508ca0d3220452854b3ec977d7be5ea2 (patch)
treefc71df2feda7bfed6f686e3f7aa0fa8629aebc5d /src/core/hle
parentMerge pull request #10760 from FearlessTobi/translations (diff)
parenttz_manager: Fix comparison to wrong integer (diff)
downloadyuzu-698a3eda508ca0d3220452854b3ec977d7be5ea2.tar.gz
yuzu-698a3eda508ca0d3220452854b3ec977d7be5ea2.tar.xz
yuzu-698a3eda508ca0d3220452854b3ec977d7be5ea2.zip
Merge pull request #10603 from lat9nq/tz-more-complete
core,common: Implement missing time zone data/computations
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/time/time_manager.cpp34
-rw-r--r--src/core/hle/service/time/time_manager.h4
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp26
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp150
-rw-r--r--src/core/hle/service/time/time_zone_manager.h8
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp57
-rw-r--r--src/core/hle/service/time/time_zone_service.h3
7 files changed, 232 insertions, 50 deletions
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 28667710e..fa0fd0531 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -22,10 +22,6 @@ s64 GetSecondsSinceEpoch() {
22 return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() + 22 return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() +
23 Settings::values.custom_rtc_differential; 23 Settings::values.custom_rtc_differential;
24} 24}
25
26s64 GetExternalRtcValue() {
27 return GetSecondsSinceEpoch() + TimeManager::GetExternalTimeZoneOffset();
28}
29} // Anonymous namespace 25} // Anonymous namespace
30 26
31struct TimeManager::Impl final { 27struct TimeManager::Impl final {
@@ -43,7 +39,7 @@ struct TimeManager::Impl final {
43 std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, 39 std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
44 time_zone_content_manager{system} { 40 time_zone_content_manager{system} {
45 41
46 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; 42 const auto system_time{Clock::TimeSpanType::FromSeconds(GetSecondsSinceEpoch())};
47 SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {}); 43 SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {});
48 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); 44 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
49 45
@@ -107,7 +103,7 @@ struct TimeManager::Impl final {
107 103
108 void SetupTimeZoneManager(std::string location_name, 104 void SetupTimeZoneManager(std::string location_name,
109 Clock::SteadyClockTimePoint time_zone_updated_time_point, 105 Clock::SteadyClockTimePoint time_zone_updated_time_point,
110 std::size_t total_location_name_count, u128 time_zone_rule_version, 106 std::vector<std::string> location_names, u128 time_zone_rule_version,
111 FileSys::VirtualFile& vfs_file) { 107 FileSys::VirtualFile& vfs_file) {
112 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( 108 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
113 location_name, vfs_file) != ResultSuccess) { 109 location_name, vfs_file) != ResultSuccess) {
@@ -117,20 +113,13 @@ struct TimeManager::Impl final {
117 113
118 time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); 114 time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
119 time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( 115 time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
120 total_location_name_count); 116 location_names.size());
117 time_zone_content_manager.GetTimeZoneManager().SetLocationNames(location_names);
121 time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion( 118 time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
122 time_zone_rule_version); 119 time_zone_rule_version);
123 time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); 120 time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
124 } 121 }
125 122
126 static s64 GetExternalTimeZoneOffset() {
127 // With "auto" timezone setting, we use the external system's timezone offset
128 if (Settings::GetTimeZoneString() == "auto") {
129 return Common::TimeZone::GetCurrentOffsetSeconds().count();
130 }
131 return 0;
132 }
133
134 void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id, 123 void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id,
135 Clock::TimeSpanType setup_value, 124 Clock::TimeSpanType setup_value,
136 Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { 125 Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
@@ -295,19 +284,10 @@ void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
295 284
296void TimeManager::SetupTimeZoneManager(std::string location_name, 285void TimeManager::SetupTimeZoneManager(std::string location_name,
297 Clock::SteadyClockTimePoint time_zone_updated_time_point, 286 Clock::SteadyClockTimePoint time_zone_updated_time_point,
298 std::size_t total_location_name_count, 287 std::vector<std::string> location_names,
299 u128 time_zone_rule_version, 288 u128 time_zone_rule_version,
300 FileSys::VirtualFile& vfs_file) { 289 FileSys::VirtualFile& vfs_file) {
301 impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, 290 impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, location_names,
302 total_location_name_count, time_zone_rule_version, vfs_file); 291 time_zone_rule_version, vfs_file);
303} 292}
304
305/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() {
306 // With "auto" timezone setting, we use the external system's timezone offset
307 if (Settings::GetTimeZoneString() == "auto") {
308 return Common::TimeZone::GetCurrentOffsetSeconds().count();
309 }
310 return 0;
311}
312
313} // namespace Service::Time 293} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h
index 4f046f266..84572dbfa 100644
--- a/src/core/hle/service/time/time_manager.h
+++ b/src/core/hle/service/time/time_manager.h
@@ -61,11 +61,9 @@ public:
61 61
62 void SetupTimeZoneManager(std::string location_name, 62 void SetupTimeZoneManager(std::string location_name,
63 Clock::SteadyClockTimePoint time_zone_updated_time_point, 63 Clock::SteadyClockTimePoint time_zone_updated_time_point,
64 std::size_t total_location_name_count, u128 time_zone_rule_version, 64 std::vector<std::string> location_names, u128 time_zone_rule_version,
65 FileSys::VirtualFile& vfs_file); 65 FileSys::VirtualFile& vfs_file);
66 66
67 static s64 GetExternalTimeZoneOffset();
68
69private: 67private:
70 Core::System& system; 68 Core::System& system;
71 69
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index afbfe9715..5d60be67a 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <chrono>
4#include <sstream> 5#include <sstream>
5 6
6#include "common/logging/log.h" 7#include "common/logging/log.h"
@@ -12,7 +13,11 @@
12#include "core/file_sys/registered_cache.h" 13#include "core/file_sys/registered_cache.h"
13#include "core/file_sys/romfs.h" 14#include "core/file_sys/romfs.h"
14#include "core/file_sys/system_archive/system_archive.h" 15#include "core/file_sys/system_archive/system_archive.h"
16#include "core/file_sys/vfs.h"
17#include "core/file_sys/vfs_types.h"
18#include "core/hle/result.h"
15#include "core/hle/service/filesystem/filesystem.h" 19#include "core/hle/service/filesystem/filesystem.h"
20#include "core/hle/service/time/errors.h"
16#include "core/hle/service/time/time_manager.h" 21#include "core/hle/service/time/time_manager.h"
17#include "core/hle/service/time/time_zone_content_manager.h" 22#include "core/hle/service/time/time_zone_content_manager.h"
18 23
@@ -71,19 +76,13 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
71 : system{system_}, location_name_cache{BuildLocationNameCache(system)} {} 76 : system{system_}, location_name_cache{BuildLocationNameCache(system)} {}
72 77
73void TimeZoneContentManager::Initialize(TimeManager& time_manager) { 78void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
74 std::string location_name;
75 const auto timezone_setting = Settings::GetTimeZoneString(); 79 const auto timezone_setting = Settings::GetTimeZoneString();
76 if (timezone_setting == "auto" || timezone_setting == "default") {
77 location_name = Common::TimeZone::GetDefaultTimeZone();
78 } else {
79 location_name = timezone_setting;
80 }
81 80
82 if (FileSys::VirtualFile vfs_file; 81 if (FileSys::VirtualFile vfs_file;
83 GetTimeZoneInfoFile(location_name, vfs_file) == ResultSuccess) { 82 GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
84 const auto time_point{ 83 const auto time_point{
85 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)}; 84 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
86 time_manager.SetupTimeZoneManager(location_name, time_point, location_name_cache.size(), {}, 85 time_manager.SetupTimeZoneManager(timezone_setting, time_point, location_name_cache, {},
87 vfs_file); 86 vfs_file);
88 } else { 87 } else {
89 time_zone_manager.MarkAsInitialized(); 88 time_zone_manager.MarkAsInitialized();
@@ -126,8 +125,15 @@ Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_n
126 125
127 vfs_file = zoneinfo_dir->GetFileRelative(location_name); 126 vfs_file = zoneinfo_dir->GetFileRelative(location_name);
128 if (!vfs_file) { 127 if (!vfs_file) {
129 LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.", 128 LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using system timezone.",
130 time_zone_binary_titleid, location_name); 129 time_zone_binary_titleid, location_name);
130 const std::string system_time_zone{Common::TimeZone::FindSystemTimeZone()};
131 vfs_file = zoneinfo_dir->GetFile(system_time_zone);
132 }
133
134 if (!vfs_file) {
135 LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
136 time_zone_binary_titleid, location_name);
131 vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone()); 137 vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone());
132 } 138 }
133 139
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
index 973f7837a..e1728c06d 100644
--- a/src/core/hle/service/time/time_zone_manager.cpp
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <climits> 4#include <climits>
5#include <limits>
5 6
6#include "common/assert.h" 7#include "common/assert.h"
7#include "common/logging/log.h" 8#include "common/logging/log.h"
@@ -9,6 +10,7 @@
9#include "core/file_sys/nca_metadata.h" 10#include "core/file_sys/nca_metadata.h"
10#include "core/file_sys/registered_cache.h" 11#include "core/file_sys/registered_cache.h"
11#include "core/hle/service/time/time_zone_manager.h" 12#include "core/hle/service/time/time_zone_manager.h"
13#include "core/hle/service/time/time_zone_types.h"
12 14
13namespace Service::Time::TimeZone { 15namespace Service::Time::TimeZone {
14 16
@@ -128,10 +130,10 @@ static constexpr int GetQZName(const char* name, int offset, char delimiter) {
128} 130}
129 131
130static constexpr int GetTZName(const char* name, int offset) { 132static constexpr int GetTZName(const char* name, int offset) {
131 for (char value{name[offset]}; 133 char c;
132 value != '\0' && !IsDigit(value) && value != ',' && value != '-' && value != '+'; 134
133 offset++) { 135 while ((c = name[offset]) != '\0' && !IsDigit(c) && c != ',' && c != '-' && c != '+') {
134 value = name[offset]; 136 ++offset;
135 } 137 }
136 return offset; 138 return offset;
137} 139}
@@ -147,6 +149,7 @@ static constexpr bool GetInteger(const char* name, int& offset, int& value, int
147 if (value > max) { 149 if (value > max) {
148 return {}; 150 return {};
149 } 151 }
152 offset++;
150 temp = name[offset]; 153 temp = name[offset];
151 } while (IsDigit(temp)); 154 } while (IsDigit(temp));
152 155
@@ -471,6 +474,13 @@ static bool ParsePosixName(const char* name, TimeZoneRule& rule) {
471 their_std_offset = their_offset; 474 their_std_offset = their_offset;
472 } 475 }
473 } 476 }
477
478 if (rule.time_count > 0) {
479 UNIMPLEMENTED();
480 // TODO (lat9nq): Implement eggert/tz/localtime.c:tzparse:1329
481 // Seems to be unused in yuzu for now: I never hit the UNIMPLEMENTED in testing
482 }
483
474 rule.ttis[0].gmt_offset = -std_offset; 484 rule.ttis[0].gmt_offset = -std_offset;
475 rule.ttis[0].is_dst = false; 485 rule.ttis[0].is_dst = false;
476 rule.ttis[0].abbreviation_list_index = 0; 486 rule.ttis[0].abbreviation_list_index = 0;
@@ -514,6 +524,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
514 524
515 constexpr s32 time_zone_max_leaps{50}; 525 constexpr s32 time_zone_max_leaps{50};
516 constexpr s32 time_zone_max_chars{50}; 526 constexpr s32 time_zone_max_chars{50};
527 constexpr s32 time_zone_max_times{1000};
517 if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps && 528 if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps &&
518 0 < header.type_count && header.type_count < s32(time_zone_rule.ttis.size()) && 529 0 < header.type_count && header.type_count < s32(time_zone_rule.ttis.size()) &&
519 0 <= header.time_count && header.time_count < s32(time_zone_rule.ats.size()) && 530 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
546 for (int index{}; index < time_zone_rule.time_count; ++index) { 557 for (int index{}; index < time_zone_rule.time_count; ++index) {
547 const u8 type{*vfs_file->ReadByte(read_offset)}; 558 const u8 type{*vfs_file->ReadByte(read_offset)};
548 read_offset += sizeof(u8); 559 read_offset += sizeof(u8);
549 if (time_zone_rule.time_count <= type) { 560 if (time_zone_rule.type_count <= type) {
550 return {}; 561 return {};
551 } 562 }
552 if (time_zone_rule.types[index] != 0) { 563 if (time_zone_rule.types[index] != 0) {
@@ -624,16 +635,109 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
624 std::array<char, time_zone_name_max> name{}; 635 std::array<char, time_zone_name_max> name{};
625 std::memcpy(name.data(), temp_name.data() + 1, std::size_t(bytes_read - 1)); 636 std::memcpy(name.data(), temp_name.data() + 1, std::size_t(bytes_read - 1));
626 637
638 // Fill in computed transition times with temp rule
627 TimeZoneRule temp_rule; 639 TimeZoneRule temp_rule;
628 if (ParsePosixName(name.data(), temp_rule)) { 640 if (ParsePosixName(name.data(), temp_rule)) {
629 UNIMPLEMENTED(); 641 int have_abbreviation = 0;
642 int char_count = time_zone_rule.char_count;
643
644 for (int i = 0; i < temp_rule.type_count; i++) {
645 char* temp_abbreviation =
646 temp_rule.chars.data() + temp_rule.ttis[i].abbreviation_list_index;
647 int j;
648 for (j = 0; j < char_count; j++) {
649 if (std::strcmp(time_zone_rule.chars.data() + j, temp_abbreviation) == 0) {
650 temp_rule.ttis[i].abbreviation_list_index = j;
651 have_abbreviation++;
652 break;
653 }
654 }
655 if (j >= char_count) {
656 int temp_abbreviation_length = static_cast<int>(std::strlen(temp_abbreviation));
657 if (j + temp_abbreviation_length < time_zone_max_chars) {
658 std::strcpy(time_zone_rule.chars.data() + j, temp_abbreviation);
659 char_count = j + temp_abbreviation_length + 1;
660 temp_rule.ttis[i].abbreviation_list_index = j;
661 have_abbreviation++;
662 }
663 }
664 }
665
666 if (have_abbreviation == temp_rule.type_count) {
667 time_zone_rule.char_count = char_count;
668
669 // Original comment:
670 /* Ignore any trailing, no-op transitions generated
671 by zic as they don't help here and can run afoul
672 of bugs in zic 2016j or earlier. */
673 // This is possibly unnecessary for yuzu, since Nintendo doesn't run zic
674 while (1 < time_zone_rule.time_count &&
675 (time_zone_rule.types[time_zone_rule.time_count - 1] ==
676 time_zone_rule.types[time_zone_rule.time_count - 2])) {
677 time_zone_rule.time_count--;
678 }
679
680 for (int i = 0;
681 i < temp_rule.time_count && time_zone_rule.time_count < time_zone_max_times;
682 i++) {
683 const s64 transition_time = temp_rule.ats[i];
684 if (0 < time_zone_rule.time_count &&
685 transition_time <= time_zone_rule.ats[time_zone_rule.time_count - 1]) {
686 continue;
687 }
688
689 time_zone_rule.ats[time_zone_rule.time_count] = transition_time;
690 time_zone_rule.types[time_zone_rule.time_count] =
691 static_cast<s8>(time_zone_rule.type_count + temp_rule.types[i]);
692 time_zone_rule.time_count++;
693 }
694 for (int i = 0; i < temp_rule.type_count; i++) {
695 time_zone_rule.ttis[time_zone_rule.type_count++] = temp_rule.ttis[i];
696 }
697 }
630 } 698 }
631 } 699 }
700
701 const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool {
702 if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) {
703 return {};
704 }
705
706 const struct TimeTypeInfo* ap = &rule.ttis[a];
707 const struct TimeTypeInfo* bp = &rule.ttis[b];
708
709 return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst &&
710 (std::strcmp(&rule.chars[ap->abbreviation_list_index],
711 &rule.chars[bp->abbreviation_list_index]) == 0));
712 };
713
632 if (time_zone_rule.type_count == 0) { 714 if (time_zone_rule.type_count == 0) {
633 return {}; 715 return {};
634 } 716 }
635 if (time_zone_rule.time_count > 1) { 717 if (time_zone_rule.time_count > 1) {
636 UNIMPLEMENTED(); 718 if (time_zone_rule.ats[0] <= std::numeric_limits<s64>::max() - seconds_per_repeat) {
719 s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat;
720 int repeatattype = time_zone_rule.types[0];
721 for (int i = 1; i < time_zone_rule.time_count; ++i) {
722 if (time_zone_rule.ats[i] == repeatat &&
723 typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
724 time_zone_rule.go_back = true;
725 break;
726 }
727 }
728 }
729 if (std::numeric_limits<s64>::min() + seconds_per_repeat <=
730 time_zone_rule.ats[time_zone_rule.time_count - 1]) {
731 s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat;
732 int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1];
733 for (int i = time_zone_rule.time_count; i >= 0; --i) {
734 if (time_zone_rule.ats[i] == repeatat &&
735 typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
736 time_zone_rule.go_ahead = true;
737 break;
738 }
739 }
740 }
637 } 741 }
638 742
639 s32 default_type{}; 743 s32 default_type{};
@@ -1038,4 +1142,36 @@ Result TimeZoneManager::GetDeviceLocationName(LocationName& value) const {
1038 return ResultSuccess; 1142 return ResultSuccess;
1039} 1143}
1040 1144
1145Result TimeZoneManager::GetTotalLocationNameCount(s32& count) const {
1146 if (!is_initialized) {
1147 return ERROR_UNINITIALIZED_CLOCK;
1148 }
1149 count = static_cast<u32>(total_location_name_count);
1150
1151 return ResultSuccess;
1152}
1153
1154Result TimeZoneManager::GetTimeZoneRuleVersion(u128& version) const {
1155 if (!is_initialized) {
1156 return ERROR_UNINITIALIZED_CLOCK;
1157 }
1158 version = time_zone_rule_version;
1159
1160 return ResultSuccess;
1161}
1162
1163Result TimeZoneManager::LoadLocationNameList(std::vector<LocationName>& values) const {
1164 if (!is_initialized) {
1165 return ERROR_UNINITIALIZED_CLOCK;
1166 }
1167
1168 for (const auto& name : total_location_names) {
1169 LocationName entry{};
1170 std::memcpy(entry.data(), name.c_str(), name.size());
1171 values.push_back(entry);
1172 }
1173
1174 return ResultSuccess;
1175}
1176
1041} // namespace Service::Time::TimeZone 1177} // namespace Service::Time::TimeZone
diff --git a/src/core/hle/service/time/time_zone_manager.h b/src/core/hle/service/time/time_zone_manager.h
index 5ebd4035e..8664f28d1 100644
--- a/src/core/hle/service/time/time_zone_manager.h
+++ b/src/core/hle/service/time/time_zone_manager.h
@@ -21,6 +21,10 @@ public:
21 total_location_name_count = value; 21 total_location_name_count = value;
22 } 22 }
23 23
24 void SetLocationNames(std::vector<std::string> location_names) {
25 total_location_names = location_names;
26 }
27
24 void SetTimeZoneRuleVersion(const u128& value) { 28 void SetTimeZoneRuleVersion(const u128& value) {
25 time_zone_rule_version = value; 29 time_zone_rule_version = value;
26 } 30 }
@@ -33,6 +37,9 @@ public:
33 FileSys::VirtualFile& vfs_file); 37 FileSys::VirtualFile& vfs_file);
34 Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value); 38 Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
35 Result GetDeviceLocationName(TimeZone::LocationName& value) const; 39 Result GetDeviceLocationName(TimeZone::LocationName& value) const;
40 Result GetTotalLocationNameCount(s32& count) const;
41 Result GetTimeZoneRuleVersion(u128& version) const;
42 Result LoadLocationNameList(std::vector<TimeZone::LocationName>& values) const;
36 Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const; 43 Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
37 Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const; 44 Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
38 Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const; 45 Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
@@ -46,6 +53,7 @@ private:
46 std::string device_location_name{"GMT"}; 53 std::string device_location_name{"GMT"};
47 u128 time_zone_rule_version{}; 54 u128 time_zone_rule_version{};
48 std::size_t total_location_name_count{}; 55 std::size_t total_location_name_count{};
56 std::vector<std::string> total_location_names{};
49 Clock::SteadyClockTimePoint time_zone_update_time_point{ 57 Clock::SteadyClockTimePoint time_zone_update_time_point{
50 Clock::SteadyClockTimePoint::GetRandom()}; 58 Clock::SteadyClockTimePoint::GetRandom()};
51}; 59};
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index cda8d8343..e8273e152 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -15,10 +15,10 @@ ITimeZoneService::ITimeZoneService(Core::System& system_,
15 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
16 {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, 16 {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
17 {1, nullptr, "SetDeviceLocationName"}, 17 {1, nullptr, "SetDeviceLocationName"},
18 {2, nullptr, "GetTotalLocationNameCount"}, 18 {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
19 {3, nullptr, "LoadLocationNameList"}, 19 {3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"},
20 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, 20 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
21 {5, nullptr, "GetTimeZoneRuleVersion"}, 21 {5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
22 {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"}, 22 {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
23 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, 23 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
24 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 24 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
@@ -45,6 +45,57 @@ void ITimeZoneService::GetDeviceLocationName(HLERequestContext& ctx) {
45 rb.PushRaw(location_name); 45 rb.PushRaw(location_name);
46} 46}
47 47
48void ITimeZoneService::GetTotalLocationNameCount(HLERequestContext& ctx) {
49 LOG_DEBUG(Service_Time, "called");
50
51 s32 count{};
52 if (const Result result{
53 time_zone_content_manager.GetTimeZoneManager().GetTotalLocationNameCount(count)};
54 result != ResultSuccess) {
55 IPC::ResponseBuilder rb{ctx, 2};
56 rb.Push(result);
57 return;
58 }
59
60 IPC::ResponseBuilder rb{ctx, 3};
61 rb.Push(ResultSuccess);
62 rb.Push(count);
63}
64
65void ITimeZoneService::LoadLocationNameList(HLERequestContext& ctx) {
66 LOG_DEBUG(Service_Time, "called");
67
68 std::vector<TimeZone::LocationName> location_names{};
69 if (const Result result{
70 time_zone_content_manager.GetTimeZoneManager().LoadLocationNameList(location_names)};
71 result != ResultSuccess) {
72 IPC::ResponseBuilder rb{ctx, 2};
73 rb.Push(result);
74 return;
75 }
76
77 ctx.WriteBuffer(location_names);
78 IPC::ResponseBuilder rb{ctx, 3};
79 rb.Push(ResultSuccess);
80 rb.Push(static_cast<s32>(location_names.size()));
81}
82void ITimeZoneService::GetTimeZoneRuleVersion(HLERequestContext& ctx) {
83 LOG_DEBUG(Service_Time, "called");
84
85 u128 rule_version{};
86 if (const Result result{
87 time_zone_content_manager.GetTimeZoneManager().GetTimeZoneRuleVersion(rule_version)};
88 result != ResultSuccess) {
89 IPC::ResponseBuilder rb{ctx, 2};
90 rb.Push(result);
91 return;
92 }
93
94 IPC::ResponseBuilder rb{ctx, 6};
95 rb.Push(ResultSuccess);
96 rb.PushRaw(rule_version);
97}
98
48void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) { 99void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) {
49 IPC::RequestParser rp{ctx}; 100 IPC::RequestParser rp{ctx};
50 const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()}; 101 const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
diff --git a/src/core/hle/service/time/time_zone_service.h b/src/core/hle/service/time/time_zone_service.h
index ea83b5714..952fcb0e2 100644
--- a/src/core/hle/service/time/time_zone_service.h
+++ b/src/core/hle/service/time/time_zone_service.h
@@ -22,6 +22,9 @@ public:
22 22
23private: 23private:
24 void GetDeviceLocationName(HLERequestContext& ctx); 24 void GetDeviceLocationName(HLERequestContext& ctx);
25 void GetTotalLocationNameCount(HLERequestContext& ctx);
26 void LoadLocationNameList(HLERequestContext& ctx);
27 void GetTimeZoneRuleVersion(HLERequestContext& ctx);
25 void LoadTimeZoneRule(HLERequestContext& ctx); 28 void LoadTimeZoneRule(HLERequestContext& ctx);
26 void ToCalendarTime(HLERequestContext& ctx); 29 void ToCalendarTime(HLERequestContext& ctx);
27 void ToCalendarTimeWithMyRule(HLERequestContext& ctx); 30 void ToCalendarTimeWithMyRule(HLERequestContext& ctx);