Просмотр исходного кода

time_zone_manager: Implement go_ahead/go_back

lat9nq 3 лет назад
Родитель
Сommit
8d52dc163a
1 измененных файлов с 39 добавлено и 1 удалено
  1. 39 1
      src/core/hle/service/time/time_zone_manager.cpp

+ 39 - 1
src/core/hle/service/time/time_zone_manager.cpp

@@ -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 {
 
@@ -629,11 +631,47 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
             UNIMPLEMENTED();
         }
     }
+
+    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{};