summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp60
1 files changed, 59 insertions, 1 deletions
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
index 54c9ecf40..24a9aa55d 100644
--- a/src/core/hle/service/time/time_zone_manager.cpp
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -524,6 +524,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
524 524
525 constexpr s32 time_zone_max_leaps{50}; 525 constexpr s32 time_zone_max_leaps{50};
526 constexpr s32 time_zone_max_chars{50}; 526 constexpr s32 time_zone_max_chars{50};
527 constexpr s32 time_zone_max_times{1000};
527 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 &&
528 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()) &&
529 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()) &&
@@ -634,9 +635,66 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
634 std::array<char, time_zone_name_max> name{}; 635 std::array<char, time_zone_name_max> name{};
635 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));
636 637
638 // Fill in computed transition times with temp rule
637 TimeZoneRule temp_rule; 639 TimeZoneRule temp_rule;
638 if (ParsePosixName(name.data(), temp_rule)) { 640 if (ParsePosixName(name.data(), temp_rule)) {
639 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 }
640 } 698 }
641 } 699 }
642 700