summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt30
-rw-r--r--src/core/file_sys/system_archive/system_archive.cpp3
-rw-r--r--src/core/file_sys/system_archive/time_zone_binary.cpp657
-rw-r--r--src/core/file_sys/system_archive/time_zone_binary.h14
-rw-r--r--src/core/hle/service/acc/acc.cpp2
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp14
-rw-r--r--src/core/hle/service/acc/profile_manager.h27
-rw-r--r--src/core/hle/service/friend/friend.cpp2
-rw-r--r--src/core/hle/service/mii/mii_manager.h156
-rw-r--r--src/core/hle/service/time/clock_types.h103
-rw-r--r--src/core/hle/service/time/ephemeral_network_system_clock_context_writer.h16
-rw-r--r--src/core/hle/service/time/ephemeral_network_system_clock_core.h17
-rw-r--r--src/core/hle/service/time/errors.h22
-rw-r--r--src/core/hle/service/time/interface.cpp19
-rw-r--r--src/core/hle/service/time/interface.h11
-rw-r--r--src/core/hle/service/time/local_system_clock_context_writer.h28
-rw-r--r--src/core/hle/service/time/network_system_clock_context_writer.h28
-rw-r--r--src/core/hle/service/time/standard_local_system_clock_core.h17
-rw-r--r--src/core/hle/service/time/standard_network_system_clock_core.h46
-rw-r--r--src/core/hle/service/time/standard_steady_clock_core.cpp26
-rw-r--r--src/core/hle/service/time/standard_steady_clock_core.h42
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.cpp77
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.h57
-rw-r--r--src/core/hle/service/time/steady_clock_core.h55
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.cpp55
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.h43
-rw-r--r--src/core/hle/service/time/system_clock_core.cpp72
-rw-r--r--src/core/hle/service/time/system_clock_core.h71
-rw-r--r--src/core/hle/service/time/tick_based_steady_clock_core.cpp24
-rw-r--r--src/core/hle/service/time/tick_based_steady_clock_core.h29
-rw-r--r--src/core/hle/service/time/time.cpp474
-rw-r--r--src/core/hle/service/time/time.h101
-rw-r--r--src/core/hle/service/time/time_manager.cpp137
-rw-r--r--src/core/hle/service/time/time_manager.h117
-rw-r--r--src/core/hle/service/time/time_sharedmemory.cpp53
-rw-r--r--src/core/hle/service/time/time_sharedmemory.h35
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp125
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.h46
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp1030
-rw-r--r--src/core/hle/service/time/time_zone_manager.h53
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp148
-rw-r--r--src/core/hle/service/time/time_zone_service.h30
-rw-r--r--src/core/hle/service/time/time_zone_types.h87
-rw-r--r--src/video_core/engines/maxwell_3d.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp14
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp6
47 files changed, 3681 insertions, 542 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7fd226050..1a3647a67 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -96,6 +96,8 @@ add_library(core STATIC
96 file_sys/system_archive/system_archive.h 96 file_sys/system_archive/system_archive.h
97 file_sys/system_archive/system_version.cpp 97 file_sys/system_archive/system_version.cpp
98 file_sys/system_archive/system_version.h 98 file_sys/system_archive/system_version.h
99 file_sys/system_archive/time_zone_binary.cpp
100 file_sys/system_archive/time_zone_binary.h
99 file_sys/vfs.cpp 101 file_sys/vfs.cpp
100 file_sys/vfs.h 102 file_sys/vfs.h
101 file_sys/vfs_concat.cpp 103 file_sys/vfs_concat.cpp
@@ -461,12 +463,40 @@ add_library(core STATIC
461 hle/service/spl/spl.h 463 hle/service/spl/spl.h
462 hle/service/ssl/ssl.cpp 464 hle/service/ssl/ssl.cpp
463 hle/service/ssl/ssl.h 465 hle/service/ssl/ssl.h
466 hle/service/time/clock_types.h
467 hle/service/time/ephemeral_network_system_clock_context_writer.h
468 hle/service/time/ephemeral_network_system_clock_core.h
469 hle/service/time/errors.h
464 hle/service/time/interface.cpp 470 hle/service/time/interface.cpp
465 hle/service/time/interface.h 471 hle/service/time/interface.h
472 hle/service/time/local_system_clock_context_writer.h
473 hle/service/time/network_system_clock_context_writer.h
474 hle/service/time/standard_local_system_clock_core.h
475 hle/service/time/standard_network_system_clock_core.h
476 hle/service/time/standard_steady_clock_core.cpp
477 hle/service/time/standard_steady_clock_core.h
478 hle/service/time/standard_user_system_clock_core.cpp
479 hle/service/time/standard_user_system_clock_core.h
480 hle/service/time/steady_clock_core.h
481 hle/service/time/system_clock_context_update_callback.cpp
482 hle/service/time/system_clock_context_update_callback.h
483 hle/service/time/system_clock_core.cpp
484 hle/service/time/system_clock_core.h
485 hle/service/time/tick_based_steady_clock_core.cpp
486 hle/service/time/tick_based_steady_clock_core.h
466 hle/service/time/time.cpp 487 hle/service/time/time.cpp
467 hle/service/time/time.h 488 hle/service/time/time.h
489 hle/service/time/time_manager.cpp
490 hle/service/time/time_manager.h
468 hle/service/time/time_sharedmemory.cpp 491 hle/service/time/time_sharedmemory.cpp
469 hle/service/time/time_sharedmemory.h 492 hle/service/time/time_sharedmemory.h
493 hle/service/time/time_zone_content_manager.cpp
494 hle/service/time/time_zone_content_manager.h
495 hle/service/time/time_zone_manager.cpp
496 hle/service/time/time_zone_manager.h
497 hle/service/time/time_zone_service.cpp
498 hle/service/time/time_zone_service.h
499 hle/service/time/time_zone_types.h
470 hle/service/usb/usb.cpp 500 hle/service/usb/usb.cpp
471 hle/service/usb/usb.h 501 hle/service/usb/usb.h
472 hle/service/vi/display/vi_display.cpp 502 hle/service/vi/display/vi_display.cpp
diff --git a/src/core/file_sys/system_archive/system_archive.cpp b/src/core/file_sys/system_archive/system_archive.cpp
index e93d100a5..a6696024e 100644
--- a/src/core/file_sys/system_archive/system_archive.cpp
+++ b/src/core/file_sys/system_archive/system_archive.cpp
@@ -9,6 +9,7 @@
9#include "core/file_sys/system_archive/shared_font.h" 9#include "core/file_sys/system_archive/shared_font.h"
10#include "core/file_sys/system_archive/system_archive.h" 10#include "core/file_sys/system_archive/system_archive.h"
11#include "core/file_sys/system_archive/system_version.h" 11#include "core/file_sys/system_archive/system_version.h"
12#include "core/file_sys/system_archive/time_zone_binary.h"
12 13
13namespace FileSys::SystemArchive { 14namespace FileSys::SystemArchive {
14 15
@@ -38,7 +39,7 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
38 {0x010000000000080B, "LocalNews", nullptr}, 39 {0x010000000000080B, "LocalNews", nullptr},
39 {0x010000000000080C, "Eula", nullptr}, 40 {0x010000000000080C, "Eula", nullptr},
40 {0x010000000000080D, "UrlBlackList", nullptr}, 41 {0x010000000000080D, "UrlBlackList", nullptr},
41 {0x010000000000080E, "TimeZoneBinary", nullptr}, 42 {0x010000000000080E, "TimeZoneBinary", &TimeZoneBinary},
42 {0x010000000000080F, "CertStoreCruiser", nullptr}, 43 {0x010000000000080F, "CertStoreCruiser", nullptr},
43 {0x0100000000000810, "FontNintendoExtension", &FontNintendoExtension}, 44 {0x0100000000000810, "FontNintendoExtension", &FontNintendoExtension},
44 {0x0100000000000811, "FontStandard", &FontStandard}, 45 {0x0100000000000811, "FontStandard", &FontStandard},
diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp
new file mode 100644
index 000000000..9806bd197
--- /dev/null
+++ b/src/core/file_sys/system_archive/time_zone_binary.cpp
@@ -0,0 +1,657 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/swap.h"
6#include "core/file_sys/system_archive/time_zone_binary.h"
7#include "core/file_sys/vfs_vector.h"
8#include "core/hle/service/time/time_zone_types.h"
9
10namespace FileSys::SystemArchive {
11
12static constexpr std::array<u8, 9633> LOCATION_NAMES{
13 0x43, 0x45, 0x54, 0x0d, 0x0a, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0d, 0x0a, 0x43, 0x75,
14 0x62, 0x61, 0x0d, 0x0a, 0x45, 0x45, 0x54, 0x0d, 0x0a, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0d, 0x0a,
15 0x45, 0x69, 0x72, 0x65, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45,
16 0x44, 0x54, 0x0d, 0x0a, 0x47, 0x42, 0x0d, 0x0a, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0d,
17 0x0a, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54,
18 0x2d, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77,
19 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x48,
20 0x53, 0x54, 0x0d, 0x0a, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x49, 0x72, 0x61,
21 0x6e, 0x0d, 0x0a, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0d, 0x0a, 0x4a, 0x61, 0x6d, 0x61, 0x69,
22 0x63, 0x61, 0x0d, 0x0a, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x4b, 0x77, 0x61, 0x6a, 0x61,
23 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x0d, 0x0a, 0x4d, 0x45, 0x54,
24 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0d, 0x0a,
25 0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0d, 0x0a, 0x4e, 0x5a, 0x0d, 0x0a, 0x4e, 0x5a, 0x2d, 0x43,
26 0x48, 0x41, 0x54, 0x0d, 0x0a, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x50, 0x6f, 0x72,
27 0x74, 0x75, 0x67, 0x61, 0x6c, 0x0d, 0x0a, 0x50, 0x52, 0x43, 0x0d, 0x0a, 0x50, 0x53, 0x54, 0x38,
28 0x50, 0x44, 0x54, 0x0d, 0x0a, 0x52, 0x4f, 0x43, 0x0d, 0x0a, 0x52, 0x4f, 0x4b, 0x0d, 0x0a, 0x53,
29 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
30 0x0d, 0x0a, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c,
31 0x0d, 0x0a, 0x55, 0x54, 0x43, 0x0d, 0x0a, 0x57, 0x2d, 0x53, 0x55, 0x0d, 0x0a, 0x57, 0x45, 0x54,
32 0x0d, 0x0a, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
33 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
34 0x63, 0x63, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64,
35 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
36 0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
37 0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
38 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
39 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61,
40 0x6e, 0x67, 0x75, 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
41 0x6a, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73,
42 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74,
43 0x79, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a,
44 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
45 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63,
46 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
47 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
48 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
49 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
50 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
51 0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0d, 0x0a, 0x41, 0x66,
52 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x41,
53 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x66,
54 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0d, 0x0a, 0x41,
55 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0d, 0x0a,
56 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0d,
57 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0d, 0x0a,
58 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62,
59 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61,
60 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61,
61 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
62 0x6d, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
63 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73,
64 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0d,
65 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c,
66 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0d,
67 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0d, 0x0a,
68 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68,
69 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61,
70 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0d,
71 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0d, 0x0a,
72 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0d, 0x0a, 0x41,
73 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41,
74 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0d,
75 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61,
76 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
77 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e,
78 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
79 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68,
80 0x6f, 0x74, 0x74, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67,
81 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
82 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
83 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72,
84 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0d, 0x0a, 0x41, 0x66,
85 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x66,
86 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
87 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
88 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
89 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
90 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0d, 0x0a,
91 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0d,
92 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69,
93 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62,
94 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63,
95 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x69,
96 0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
97 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68,
98 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69,
99 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
100 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0d, 0x0a, 0x41, 0x6d,
101 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
102 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
103 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f,
104 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
105 0x69, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
106 0x67, 0x6f, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
107 0x69, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65,
108 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
109 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79,
110 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f,
111 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
112 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
113 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
114 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
115 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
116 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
117 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
118 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0d,
119 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48,
120 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
121 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
122 0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
123 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d,
124 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
125 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0d, 0x0a, 0x41,
126 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68,
127 0x61, 0x76, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
128 0x73, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
129 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
130 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
131 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
132 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
133 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x0d, 0x0a,
134 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65,
135 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c,
136 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
137 0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
138 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
139 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0d,
140 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61,
141 0x79, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61,
142 0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
143 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
144 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
145 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0d, 0x0a,
146 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d,
147 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
148 0x75, 0x70, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61,
149 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
150 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
151 0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
152 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
153 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
154 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a,
155 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70,
156 0x6f, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
157 0x75, 0x76, 0x69, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
158 0x61, 0x6c, 0x75, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
159 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
160 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
161 0x75, 0x6e, 0x65, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b,
162 0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
163 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
164 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
165 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
166 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0d, 0x0a, 0x41,
167 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c,
168 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72,
169 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
170 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
171 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
172 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
173 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
174 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0d, 0x0a,
175 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f,
176 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74,
177 0x6c, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e,
178 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
179 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
180 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
181 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
182 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79,
183 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c,
184 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63,
185 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e,
186 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
187 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
188 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x0d, 0x0a, 0x41, 0x6d,
189 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74,
190 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75,
191 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f,
192 0x72, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69,
193 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
194 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e,
195 0x68, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e,
196 0x61, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
197 0x61, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
198 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
199 0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
200 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0d, 0x0a, 0x41,
201 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50,
202 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
203 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
204 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0d, 0x0a,
205 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f,
206 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
207 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
208 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73,
209 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f,
210 0x52, 0x69, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
211 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
212 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
213 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
214 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x41,
215 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63,
216 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x73, 0x61, 0x72,
217 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74,
218 0x61, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
219 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
220 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
221 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69,
222 0x6e, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f,
223 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
224 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x6d,
225 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68, 0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0d, 0x0a,
226 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
227 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65,
228 0x6c, 0x65, 0x6d, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74,
229 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
230 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
231 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
232 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0d, 0x0a, 0x41,
233 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
234 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74,
235 0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
236 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0d, 0x0a, 0x41,
237 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
238 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61,
239 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
240 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f,
241 0x6e, 0x74, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72,
242 0x74, 0x6f, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61,
243 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
244 0x2f, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
245 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
246 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0d, 0x0a, 0x41,
247 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0d, 0x0a,
248 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e,
249 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
250 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69,
251 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
252 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61,
253 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74,
254 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76,
255 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
256 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41,
257 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
258 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
259 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f,
260 0x6a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
261 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41,
262 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
263 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x41,
264 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
265 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
266 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75,
267 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
268 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x0d, 0x0a,
269 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e,
270 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
271 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68,
272 0x75, 0x61, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
273 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c,
274 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
275 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
276 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
277 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
278 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
279 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54,
280 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
281 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0d,
282 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
283 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
284 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61,
285 0x6d, 0x61, 0x63, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
286 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65,
287 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63,
288 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, 0x41,
289 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b,
290 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
291 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
292 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
293 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65,
294 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
295 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72,
296 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6e, 0x74,
297 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55,
298 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
299 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0d, 0x0a, 0x41, 0x6e,
300 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0d,
301 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75,
302 0x72, 0x64, 0x6f, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
303 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
304 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61,
305 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c,
306 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79,
307 0x6f, 0x77, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
308 0x54, 0x72, 0x6f, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
309 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63,
310 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41,
311 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41,
312 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61,
313 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0d, 0x0a,
314 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
315 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73,
316 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68,
317 0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79,
318 0x72, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61,
319 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0d,
320 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
321 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42,
322 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69,
323 0x72, 0x75, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65,
324 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0d, 0x0a,
325 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0d, 0x0a, 0x41,
326 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
327 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
328 0x2f, 0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
329 0x2f, 0x43, 0x68, 0x75, 0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
330 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
331 0x61, 0x63, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73,
332 0x63, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0d,
333 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
334 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73,
335 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61,
336 0x67, 0x75, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61,
337 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0d, 0x0a, 0x41,
338 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
339 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
340 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x5f, 0x43,
341 0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72,
342 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61,
343 0x6e, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72,
344 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72,
345 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
346 0x6d, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
347 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
348 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69,
349 0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
350 0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
351 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
352 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x6f,
353 0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73,
354 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
355 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
356 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
357 0x75, 0x77, 0x61, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61,
358 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0d, 0x0a, 0x41,
359 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69,
360 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
361 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
362 0x73, 0x63, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73,
363 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a,
364 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
365 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d,
366 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x41,
367 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0d, 0x0a,
368 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0d, 0x0a,
369 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0d, 0x0a,
370 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
371 0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
372 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52,
373 0x69, 0x79, 0x61, 0x64, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67,
374 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69,
375 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e,
376 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
377 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73,
378 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x73,
379 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
380 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0d, 0x0a, 0x41,
381 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x73,
382 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
383 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65,
384 0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
385 0x6d, 0x62, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68,
386 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0d, 0x0a, 0x41,
387 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
388 0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x67, 0x0d, 0x0a, 0x41,
389 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0d,
390 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f, 0x72,
391 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0d, 0x0a, 0x41,
392 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x73,
393 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x73,
394 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a,
395 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73,
396 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
397 0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
398 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
399 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x74,
400 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0d, 0x0a,
401 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0d,
402 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56,
403 0x65, 0x72, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46,
404 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
405 0x46, 0x61, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
406 0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
407 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
408 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0d,
409 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f,
410 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
411 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
412 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0d, 0x0a, 0x41,
413 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0d, 0x0a, 0x41, 0x75,
414 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65,
415 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73,
416 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
417 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x75, 0x73,
418 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65, 0x72, 0x72, 0x61, 0x0d,
419 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69,
420 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72,
421 0x77, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45,
422 0x75, 0x63, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
423 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
424 0x61, 0x2f, 0x4c, 0x48, 0x49, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
425 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72,
426 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0d, 0x0a,
427 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75,
428 0x72, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e,
429 0x6f, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
430 0x4e, 0x53, 0x57, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
431 0x65, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
432 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74,
433 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73,
434 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0d, 0x0a, 0x41,
435 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69,
436 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x63,
437 0x74, 0x6f, 0x72, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
438 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
439 0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61,
440 0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c,
441 0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a,
442 0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f,
443 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x41, 0x74, 0x6c,
444 0x61, 0x6e, 0x74, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x43, 0x65,
445 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61,
446 0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d,
447 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0d,
448 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e,
449 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e,
450 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50, 0x61,
451 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x53, 0x61,
452 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61,
453 0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0d, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f,
454 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x68, 0x69,
455 0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
456 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
457 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0d, 0x0a,
458 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
459 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
460 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0d, 0x0a, 0x45,
461 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
462 0x54, 0x2b, 0x34, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0d, 0x0a,
463 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
464 0x4d, 0x54, 0x2b, 0x37, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0d,
465 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
466 0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31,
467 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74,
468 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
469 0x54, 0x2d, 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33,
470 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0d, 0x0a, 0x45, 0x74,
471 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
472 0x2d, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0d, 0x0a, 0x45,
473 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
474 0x54, 0x2d, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0d, 0x0a,
475 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
476 0x4d, 0x54, 0x2d, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a,
477 0x45, 0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x45,
478 0x74, 0x63, 0x2f, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x6e, 0x69, 0x76,
479 0x65, 0x72, 0x73, 0x61, 0x6c, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0d, 0x0a,
480 0x45, 0x74, 0x63, 0x2f, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
481 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
482 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
483 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
484 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72,
485 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72,
486 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x45, 0x75,
487 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72,
488 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0d, 0x0a,
489 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0d,
490 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73,
491 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
492 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e,
493 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
494 0x69, 0x6e, 0x61, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70,
495 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
496 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
497 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
498 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
499 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
500 0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0d, 0x0a,
501 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0d,
502 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0d, 0x0a,
503 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72,
504 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0d,
505 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0d, 0x0a, 0x45,
506 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
507 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0d, 0x0a,
508 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0d, 0x0a, 0x45,
509 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67,
510 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x0d,
511 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x45,
512 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0d,
513 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0d, 0x0a, 0x45,
514 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0d, 0x0a, 0x45, 0x75,
515 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72,
516 0x6f, 0x70, 0x65, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72,
517 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
518 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50,
519 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
520 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
521 0x52, 0x69, 0x67, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d,
522 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61,
523 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72,
524 0x69, 0x6e, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61,
525 0x6a, 0x65, 0x76, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72,
526 0x61, 0x74, 0x6f, 0x76, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
527 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
528 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53,
529 0x6f, 0x66, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f,
530 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
531 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
532 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69,
533 0x72, 0x61, 0x73, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55,
534 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
535 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
536 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
537 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
538 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
539 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
540 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
541 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
542 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a,
543 0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
544 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
545 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0d, 0x0a, 0x49,
546 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
547 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0d, 0x0a,
548 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
549 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
550 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0d, 0x0a, 0x49,
551 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x68, 0x65, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69,
552 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
553 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x49,
554 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0d, 0x0a, 0x49,
555 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x4d,
556 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74, 0x65, 0x0d,
557 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72, 0x0d,
558 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0d,
559 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0d, 0x0a, 0x50,
560 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
561 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e,
562 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43,
563 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
564 0x43, 0x68, 0x75, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
565 0x61, 0x73, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
566 0x66, 0x61, 0x74, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e,
567 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
568 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
569 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
570 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
571 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63,
572 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61,
573 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61,
574 0x6c, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0d,
575 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c,
576 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73,
577 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72,
578 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
579 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
580 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
581 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
582 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0d, 0x0a, 0x50,
583 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0d, 0x0a, 0x50,
584 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0d, 0x0a, 0x50, 0x61,
585 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
586 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63,
587 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63,
588 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0d, 0x0a,
589 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0d, 0x0a, 0x50,
590 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x0d,
591 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69,
592 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65,
593 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d,
594 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
595 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
596 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
597 0x69, 0x63, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
598 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
599 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
600 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63,
601 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
602 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
603 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
604 0x2f, 0x59, 0x61, 0x70, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0d,
605 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
606 0x2f, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e,
607 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e,
608 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
609 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x0d, 0x0a, 0x55, 0x53,
610 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0d,
611 0x0a, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69, 0x67, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
612 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61,
613 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
614 0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d,
615 0x0a};
616
617static VirtualFile GenerateDefaultTimeZoneFile() {
618 struct {
619 s64_be at;
620 INSERT_PADDING_BYTES(7);
621 std::array<char, 4> time_zone_chars;
622 INSERT_PADDING_BYTES(2);
623 std::array<char, 6> time_zone_name;
624 } time_zone_info{};
625
626 const VirtualFile file{std::make_shared<VectorVfsFile>(
627 std::vector<u8>(sizeof(Service::Time::TimeZone::TzifHeader) + sizeof(time_zone_info)),
628 "GMT")};
629
630 Service::Time::TimeZone::TzifHeader header{};
631 header.magic = 0x545a6966;
632 header.version = 0x32;
633 header.ttis_gmt_count = 0x1;
634 header.ttis_std_count = 0x1;
635 header.time_count = 0x1;
636 header.type_count = 0x1;
637 header.char_count = 0x4;
638 file->WriteObject(header, 0);
639
640 time_zone_info.at = 0xf8;
641 time_zone_info.time_zone_chars = {'G', 'M', 'T', '\0'};
642 time_zone_info.time_zone_name = {'\n', 'G', 'M', 'T', '0', '\n'};
643 file->WriteObject(time_zone_info, sizeof(Service::Time::TimeZone::TzifHeader));
644
645 return file;
646}
647
648VirtualDir TimeZoneBinary() {
649 const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
650 std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{},
651 "zoneinfo")};
652 const std::vector<VirtualFile> root_files{
653 std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")};
654 return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data");
655}
656
657} // namespace FileSys::SystemArchive
diff --git a/src/core/file_sys/system_archive/time_zone_binary.h b/src/core/file_sys/system_archive/time_zone_binary.h
new file mode 100644
index 000000000..ed2b78227
--- /dev/null
+++ b/src/core/file_sys/system_archive/time_zone_binary.h
@@ -0,0 +1,14 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8#include "core/file_sys/vfs_types.h"
9
10namespace FileSys::SystemArchive {
11
12VirtualDir TimeZoneBinary();
13
14} // namespace FileSys::SystemArchive
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 7e3e311fb..cfac8ca9a 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -211,7 +211,7 @@ protected:
211 } 211 }
212 212
213 ProfileManager& profile_manager; 213 ProfileManager& profile_manager;
214 Common::UUID user_id; ///< The user id this profile refers to. 214 Common::UUID user_id{Common::INVALID_UUID}; ///< The user id this profile refers to.
215}; 215};
216 216
217class IProfile final : public IProfileCommon { 217class IProfile final : public IProfileCommon {
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 3e756e59e..eb8c81645 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -16,17 +16,17 @@ namespace Service::Account {
16using Common::UUID; 16using Common::UUID;
17 17
18struct UserRaw { 18struct UserRaw {
19 UUID uuid; 19 UUID uuid{Common::INVALID_UUID};
20 UUID uuid2; 20 UUID uuid2{Common::INVALID_UUID};
21 u64 timestamp; 21 u64 timestamp{};
22 ProfileUsername username; 22 ProfileUsername username{};
23 ProfileData extra_data; 23 ProfileData extra_data{};
24}; 24};
25static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size."); 25static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size.");
26 26
27struct ProfileDataRaw { 27struct ProfileDataRaw {
28 INSERT_PADDING_BYTES(0x10); 28 INSERT_PADDING_BYTES(0x10);
29 std::array<UserRaw, MAX_USERS> users; 29 std::array<UserRaw, MAX_USERS> users{};
30}; 30};
31static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size."); 31static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size.");
32 32
@@ -238,7 +238,7 @@ UserIDArray ProfileManager::GetOpenUsers() const {
238 std::transform(profiles.begin(), profiles.end(), output.begin(), [](const ProfileInfo& p) { 238 std::transform(profiles.begin(), profiles.end(), output.begin(), [](const ProfileInfo& p) {
239 if (p.is_open) 239 if (p.is_open)
240 return p.user_uuid; 240 return p.user_uuid;
241 return UUID{}; 241 return UUID{Common::INVALID_UUID};
242 }); 242 });
243 std::stable_partition(output.begin(), output.end(), [](const UUID& uuid) { return uuid; }); 243 std::stable_partition(output.begin(), output.end(), [](const UUID& uuid) { return uuid; });
244 return output; 244 return output;
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 5a6d28925..5310637a6 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -13,9 +13,10 @@
13#include "core/hle/result.h" 13#include "core/hle/result.h"
14 14
15namespace Service::Account { 15namespace Service::Account {
16constexpr std::size_t MAX_USERS = 8;
17 16
18constexpr std::size_t profile_username_size = 32; 17constexpr std::size_t MAX_USERS{8};
18constexpr std::size_t profile_username_size{32};
19
19using ProfileUsername = std::array<u8, profile_username_size>; 20using ProfileUsername = std::array<u8, profile_username_size>;
20using UserIDArray = std::array<Common::UUID, MAX_USERS>; 21using UserIDArray = std::array<Common::UUID, MAX_USERS>;
21 22
@@ -23,8 +24,8 @@ using UserIDArray = std::array<Common::UUID, MAX_USERS>;
23/// TODO: RE this structure 24/// TODO: RE this structure
24struct ProfileData { 25struct ProfileData {
25 INSERT_PADDING_WORDS(1); 26 INSERT_PADDING_WORDS(1);
26 u32 icon_id; 27 u32 icon_id{};
27 u8 bg_color_id; 28 u8 bg_color_id{};
28 INSERT_PADDING_BYTES(0x7); 29 INSERT_PADDING_BYTES(0x7);
29 INSERT_PADDING_BYTES(0x10); 30 INSERT_PADDING_BYTES(0x10);
30 INSERT_PADDING_BYTES(0x60); 31 INSERT_PADDING_BYTES(0x60);
@@ -34,17 +35,17 @@ static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect
34/// This holds general information about a users profile. This is where we store all the information 35/// This holds general information about a users profile. This is where we store all the information
35/// based on a specific user 36/// based on a specific user
36struct ProfileInfo { 37struct ProfileInfo {
37 Common::UUID user_uuid; 38 Common::UUID user_uuid{Common::INVALID_UUID};
38 ProfileUsername username; 39 ProfileUsername username{};
39 u64 creation_time; 40 u64 creation_time{};
40 ProfileData data; // TODO(ognik): Work out what this is 41 ProfileData data{}; // TODO(ognik): Work out what this is
41 bool is_open; 42 bool is_open{};
42}; 43};
43 44
44struct ProfileBase { 45struct ProfileBase {
45 Common::UUID user_uuid; 46 Common::UUID user_uuid{Common::INVALID_UUID};
46 u64_le timestamp; 47 u64_le timestamp{};
47 ProfileUsername username; 48 ProfileUsername username{};
48 49
49 // Zero out all the fields to make the profile slot considered "Empty" 50 // Zero out all the fields to make the profile slot considered "Empty"
50 void Invalidate() { 51 void Invalidate() {
@@ -101,7 +102,7 @@ private:
101 bool RemoveProfileAtIndex(std::size_t index); 102 bool RemoveProfileAtIndex(std::size_t index);
102 103
103 std::array<ProfileInfo, MAX_USERS> profiles{}; 104 std::array<ProfileInfo, MAX_USERS> profiles{};
104 std::size_t user_count = 0; 105 std::size_t user_count{};
105 Common::UUID last_opened_user{Common::INVALID_UUID}; 106 Common::UUID last_opened_user{Common::INVALID_UUID};
106}; 107};
107 108
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 219176c31..6aadb3ea8 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -241,7 +241,7 @@ private:
241 bool has_received_friend_request; 241 bool has_received_friend_request;
242 }; 242 };
243 243
244 Common::UUID uuid; 244 Common::UUID uuid{Common::INVALID_UUID};
245 Kernel::EventPair notification_event; 245 Kernel::EventPair notification_event;
246 std::queue<SizedNotificationInfo> notifications; 246 std::queue<SizedNotificationInfo> notifications;
247 States states{}; 247 States states{};
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index 38ad78a0d..fc742816a 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -10,13 +10,13 @@
10 10
11namespace Service::Mii { 11namespace Service::Mii {
12 12
13constexpr std::size_t MAX_MIIS = 100; 13constexpr std::size_t MAX_MIIS{100};
14constexpr u32 INVALID_INDEX = 0xFFFFFFFF; 14constexpr u32 INVALID_INDEX{0xFFFFFFFF};
15 15
16struct RandomParameters { 16struct RandomParameters {
17 u32 unknown_1; 17 u32 unknown_1{};
18 u32 unknown_2; 18 u32 unknown_2{};
19 u32 unknown_3; 19 u32 unknown_3{};
20}; 20};
21static_assert(sizeof(RandomParameters) == 0xC, "RandomParameters has incorrect size."); 21static_assert(sizeof(RandomParameters) == 0xC, "RandomParameters has incorrect size.");
22 22
@@ -30,57 +30,57 @@ enum class Source : u32 {
30std::ostream& operator<<(std::ostream& os, Source source); 30std::ostream& operator<<(std::ostream& os, Source source);
31 31
32struct MiiInfo { 32struct MiiInfo {
33 Common::UUID uuid; 33 Common::UUID uuid{Common::INVALID_UUID};
34 std::array<char16_t, 11> name; 34 std::array<char16_t, 11> name{};
35 u8 font_region; 35 u8 font_region{};
36 u8 favorite_color; 36 u8 favorite_color{};
37 u8 gender; 37 u8 gender{};
38 u8 height; 38 u8 height{};
39 u8 weight; 39 u8 weight{};
40 u8 mii_type; 40 u8 mii_type{};
41 u8 mii_region; 41 u8 mii_region{};
42 u8 face_type; 42 u8 face_type{};
43 u8 face_color; 43 u8 face_color{};
44 u8 face_wrinkle; 44 u8 face_wrinkle{};
45 u8 face_makeup; 45 u8 face_makeup{};
46 u8 hair_type; 46 u8 hair_type{};
47 u8 hair_color; 47 u8 hair_color{};
48 bool hair_flip; 48 bool hair_flip{};
49 u8 eye_type; 49 u8 eye_type{};
50 u8 eye_color; 50 u8 eye_color{};
51 u8 eye_scale; 51 u8 eye_scale{};
52 u8 eye_aspect_ratio; 52 u8 eye_aspect_ratio{};
53 u8 eye_rotate; 53 u8 eye_rotate{};
54 u8 eye_x; 54 u8 eye_x{};
55 u8 eye_y; 55 u8 eye_y{};
56 u8 eyebrow_type; 56 u8 eyebrow_type{};
57 u8 eyebrow_color; 57 u8 eyebrow_color{};
58 u8 eyebrow_scale; 58 u8 eyebrow_scale{};
59 u8 eyebrow_aspect_ratio; 59 u8 eyebrow_aspect_ratio{};
60 u8 eyebrow_rotate; 60 u8 eyebrow_rotate{};
61 u8 eyebrow_x; 61 u8 eyebrow_x{};
62 u8 eyebrow_y; 62 u8 eyebrow_y{};
63 u8 nose_type; 63 u8 nose_type{};
64 u8 nose_scale; 64 u8 nose_scale{};
65 u8 nose_y; 65 u8 nose_y{};
66 u8 mouth_type; 66 u8 mouth_type{};
67 u8 mouth_color; 67 u8 mouth_color{};
68 u8 mouth_scale; 68 u8 mouth_scale{};
69 u8 mouth_aspect_ratio; 69 u8 mouth_aspect_ratio{};
70 u8 mouth_y; 70 u8 mouth_y{};
71 u8 facial_hair_color; 71 u8 facial_hair_color{};
72 u8 beard_type; 72 u8 beard_type{};
73 u8 mustache_type; 73 u8 mustache_type{};
74 u8 mustache_scale; 74 u8 mustache_scale{};
75 u8 mustache_y; 75 u8 mustache_y{};
76 u8 glasses_type; 76 u8 glasses_type{};
77 u8 glasses_color; 77 u8 glasses_color{};
78 u8 glasses_scale; 78 u8 glasses_scale{};
79 u8 glasses_y; 79 u8 glasses_y{};
80 u8 mole_type; 80 u8 mole_type{};
81 u8 mole_scale; 81 u8 mole_scale{};
82 u8 mole_x; 82 u8 mole_x{};
83 u8 mole_y; 83 u8 mole_y{};
84 INSERT_PADDING_BYTES(1); 84 INSERT_PADDING_BYTES(1);
85 85
86 std::u16string Name() const; 86 std::u16string Name() const;
@@ -94,14 +94,14 @@ bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs);
94 94
95#pragma pack(push, 4) 95#pragma pack(push, 4)
96struct MiiInfoElement { 96struct MiiInfoElement {
97 MiiInfo info; 97 MiiInfo info{};
98 Source source; 98 Source source{};
99}; 99};
100static_assert(sizeof(MiiInfoElement) == 0x5C, "MiiInfoElement has incorrect size."); 100static_assert(sizeof(MiiInfoElement) == 0x5C, "MiiInfoElement has incorrect size.");
101 101
102struct MiiStoreBitFields { 102struct MiiStoreBitFields {
103 union { 103 union {
104 u32 word_0; 104 u32 word_0{};
105 105
106 BitField<24, 8, u32> hair_type; 106 BitField<24, 8, u32> hair_type;
107 BitField<23, 1, u32> mole_type; 107 BitField<23, 1, u32> mole_type;
@@ -112,7 +112,7 @@ struct MiiStoreBitFields {
112 }; 112 };
113 113
114 union { 114 union {
115 u32 word_1; 115 u32 word_1{};
116 116
117 BitField<31, 1, u32> gender; 117 BitField<31, 1, u32> gender;
118 BitField<24, 7, u32> eye_color; 118 BitField<24, 7, u32> eye_color;
@@ -122,7 +122,7 @@ struct MiiStoreBitFields {
122 }; 122 };
123 123
124 union { 124 union {
125 u32 word_2; 125 u32 word_2{};
126 126
127 BitField<31, 1, u32> mii_type; 127 BitField<31, 1, u32> mii_type;
128 BitField<24, 7, u32> glasses_color; 128 BitField<24, 7, u32> glasses_color;
@@ -135,7 +135,7 @@ struct MiiStoreBitFields {
135 }; 135 };
136 136
137 union { 137 union {
138 u32 word_3; 138 u32 word_3{};
139 139
140 BitField<29, 3, u32> mustache_type; 140 BitField<29, 3, u32> mustache_type;
141 BitField<24, 5, u32> eyebrow_type; 141 BitField<24, 5, u32> eyebrow_type;
@@ -148,7 +148,7 @@ struct MiiStoreBitFields {
148 }; 148 };
149 149
150 union { 150 union {
151 u32 word_4; 151 u32 word_4{};
152 152
153 BitField<29, 3, u32> eye_rotate; 153 BitField<29, 3, u32> eye_rotate;
154 BitField<24, 5, u32> mustache_y; 154 BitField<24, 5, u32> mustache_y;
@@ -160,7 +160,7 @@ struct MiiStoreBitFields {
160 }; 160 };
161 161
162 union { 162 union {
163 u32 word_5; 163 u32 word_5{};
164 164
165 BitField<24, 5, u32> glasses_type; 165 BitField<24, 5, u32> glasses_type;
166 BitField<20, 4, u32> face_type; 166 BitField<20, 4, u32> face_type;
@@ -172,7 +172,7 @@ struct MiiStoreBitFields {
172 }; 172 };
173 173
174 union { 174 union {
175 u32 word_6; 175 u32 word_6{};
176 176
177 BitField<28, 4, u32> eyebrow_rotate; 177 BitField<28, 4, u32> eyebrow_rotate;
178 BitField<24, 4, u32> eyebrow_scale; 178 BitField<24, 4, u32> eyebrow_scale;
@@ -192,30 +192,30 @@ struct MiiStoreData {
192 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the 192 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
193 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is 193 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
194 // not suitable for our uses. 194 // not suitable for our uses.
195 std::array<u8, 0x1C> data; 195 std::array<u8, 0x1C> data{};
196 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size."); 196 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
197 197
198 std::array<char16_t, 10> name; 198 std::array<char16_t, 10> name{};
199 Common::UUID uuid; 199 Common::UUID uuid{Common::INVALID_UUID};
200 u16 crc_1; 200 u16 crc_1{};
201 u16 crc_2; 201 u16 crc_2{};
202 202
203 std::u16string Name() const; 203 std::u16string Name() const;
204}; 204};
205static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size."); 205static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
206 206
207struct MiiStoreDataElement { 207struct MiiStoreDataElement {
208 MiiStoreData data; 208 MiiStoreData data{};
209 Source source; 209 Source source{};
210}; 210};
211static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size."); 211static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
212 212
213struct MiiDatabase { 213struct MiiDatabase {
214 u32 magic; // 'NFDB' 214 u32 magic{}; // 'NFDB'
215 std::array<MiiStoreData, MAX_MIIS> miis; 215 std::array<MiiStoreData, MAX_MIIS> miis{};
216 INSERT_PADDING_BYTES(1); 216 INSERT_PADDING_BYTES(1);
217 u8 count; 217 u8 count{};
218 u16 crc; 218 u16 crc{};
219}; 219};
220static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size."); 220static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
221#pragma pack(pop) 221#pragma pack(pop)
@@ -266,8 +266,8 @@ private:
266 void EnsureDatabasePartition(); 266 void EnsureDatabasePartition();
267 267
268 MiiDatabase database; 268 MiiDatabase database;
269 bool updated_flag = false; 269 bool updated_flag{};
270 bool is_test_mode_enabled = false; 270 bool is_test_mode_enabled{};
271}; 271};
272 272
273}; // namespace Service::Mii 273}; // namespace Service::Mii
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
new file mode 100644
index 000000000..72e1921ec
--- /dev/null
+++ b/src/core/hle/service/time/clock_types.h
@@ -0,0 +1,103 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9#include "common/uuid.h"
10#include "core/hle/service/time/errors.h"
11#include "core/hle/service/time/time_zone_types.h"
12
13namespace Service::Time::Clock {
14
15/// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint
16struct SteadyClockTimePoint {
17 s64 time_point;
18 Common::UUID clock_source_id;
19
20 ResultCode GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
21 span = 0;
22
23 if (clock_source_id != other.clock_source_id) {
24 return ERROR_TIME_MISMATCH;
25 }
26
27 span = other.time_point - time_point;
28
29 return RESULT_SUCCESS;
30 }
31
32 static SteadyClockTimePoint GetRandom() {
33 return {0, Common::UUID::Generate()};
34 }
35};
36static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
37static_assert(std::is_trivially_copyable_v<SteadyClockTimePoint>,
38 "SteadyClockTimePoint must be trivially copyable");
39
40struct SteadyClockContext {
41 u64 internal_offset;
42 Common::UUID steady_time_point;
43};
44static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size");
45static_assert(std::is_trivially_copyable_v<SteadyClockContext>,
46 "SteadyClockContext must be trivially copyable");
47
48struct SystemClockContext {
49 s64 offset;
50 SteadyClockTimePoint steady_time_point;
51};
52static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorrect size");
53static_assert(std::is_trivially_copyable_v<SystemClockContext>,
54 "SystemClockContext must be trivially copyable");
55
56/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
57struct TimeSpanType {
58 s64 nanoseconds{};
59 static constexpr s64 ns_per_second{1000000000ULL};
60
61 s64 ToSeconds() const {
62 return nanoseconds / ns_per_second;
63 }
64
65 static TimeSpanType FromSeconds(s64 seconds) {
66 return {seconds * ns_per_second};
67 }
68
69 static TimeSpanType FromTicks(u64 ticks, u64 frequency) {
70 return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency));
71 }
72};
73static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size");
74
75struct ClockSnapshot {
76 SystemClockContext user_context{};
77 SystemClockContext network_context{};
78 s64 user_time{};
79 s64 network_time{};
80 TimeZone::CalendarTime user_calendar_time{};
81 TimeZone::CalendarTime network_calendar_time{};
82 TimeZone::CalendarAdditionalInfo user_calendar_additional_time{};
83 TimeZone::CalendarAdditionalInfo network_calendar_additional_time{};
84 SteadyClockTimePoint steady_clock_time_point{};
85 TimeZone::LocationName location_name{};
86 u8 is_automatic_correction_enabled{};
87 u8 type{};
88 INSERT_PADDING_BYTES(0x2);
89
90 static ResultCode GetCurrentTime(s64& current_time,
91 const SteadyClockTimePoint& steady_clock_time_point,
92 const SystemClockContext& context) {
93 if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
94 current_time = 0;
95 return ERROR_TIME_MISMATCH;
96 }
97 current_time = steady_clock_time_point.time_point + context.offset;
98 return RESULT_SUCCESS;
99 }
100};
101static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size");
102
103} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/ephemeral_network_system_clock_context_writer.h b/src/core/hle/service/time/ephemeral_network_system_clock_context_writer.h
new file mode 100644
index 000000000..42893e3f6
--- /dev/null
+++ b/src/core/hle/service/time/ephemeral_network_system_clock_context_writer.h
@@ -0,0 +1,16 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/system_clock_context_update_callback.h"
8
9namespace Service::Time::Clock {
10
11class EphemeralNetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
12public:
13 EphemeralNetworkSystemClockContextWriter() : SystemClockContextUpdateCallback{} {}
14};
15
16} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/ephemeral_network_system_clock_core.h b/src/core/hle/service/time/ephemeral_network_system_clock_core.h
new file mode 100644
index 000000000..4c6cdef86
--- /dev/null
+++ b/src/core/hle/service/time/ephemeral_network_system_clock_core.h
@@ -0,0 +1,17 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/system_clock_core.h"
8
9namespace Service::Time::Clock {
10
11class EphemeralNetworkSystemClockCore final : public SystemClockCore {
12public:
13 explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core)
14 : SystemClockCore{steady_clock_core} {}
15};
16
17} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/errors.h b/src/core/hle/service/time/errors.h
new file mode 100644
index 000000000..8501a3e8c
--- /dev/null
+++ b/src/core/hle/service/time/errors.h
@@ -0,0 +1,22 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/result.h"
8
9namespace Service::Time {
10
11constexpr ResultCode ERROR_PERMISSION_DENIED{ErrorModule::Time, 1};
12constexpr ResultCode ERROR_TIME_MISMATCH{ErrorModule::Time, 102};
13constexpr ResultCode ERROR_UNINITIALIZED_CLOCK{ErrorModule::Time, 103};
14constexpr ResultCode ERROR_TIME_NOT_FOUND{ErrorModule::Time, 200};
15constexpr ResultCode ERROR_OVERFLOW{ErrorModule::Time, 201};
16constexpr ResultCode ERROR_LOCATION_NAME_TOO_LONG{ErrorModule::Time, 801};
17constexpr ResultCode ERROR_OUT_OF_RANGE{ErrorModule::Time, 902};
18constexpr ResultCode ERROR_TIME_ZONE_CONVERSION_FAILED{ErrorModule::Time, 903};
19constexpr ResultCode ERROR_TIME_ZONE_NOT_FOUND{ErrorModule::Time, 989};
20constexpr ResultCode ERROR_NOT_IMPLEMENTED{ErrorModule::Time, 990};
21
22} // namespace Service::Time
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index bc74f1e1d..1660bbdb8 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -1,4 +1,4 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -6,9 +6,8 @@
6 6
7namespace Service::Time { 7namespace Service::Time {
8 8
9Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, 9Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* name)
10 Core::System& system, const char* name) 10 : Module::Interface(std::move(module), system, name) {
11 : Module::Interface(std::move(time), std::move(shared_memory), system, name) {
12 // clang-format off 11 // clang-format off
13 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
14 {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, 13 {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
@@ -22,15 +21,15 @@ Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_me
22 {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"}, 21 {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
23 {50, nullptr, "SetStandardSteadyClockInternalOffset"}, 22 {50, nullptr, "SetStandardSteadyClockInternalOffset"},
24 {51, nullptr, "GetStandardSteadyClockRtcValue"}, 23 {51, nullptr, "GetStandardSteadyClockRtcValue"},
25 {100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, 24 {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
26 {101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, 25 {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
27 {102, nullptr, "GetStandardUserSystemClockInitialYear"}, 26 {102, nullptr, "GetStandardUserSystemClockInitialYear"},
28 {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, 27 {200, &Time::IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
29 {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, 28 {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
30 {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"}, 29 {300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
31 {400, &Time::GetClockSnapshot, "GetClockSnapshot"}, 30 {400, &Time::GetClockSnapshot, "GetClockSnapshot"},
32 {401, nullptr, "GetClockSnapshotFromSystemClockContext"}, 31 {401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
33 {500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, 32 {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
34 {501, nullptr, "CalculateSpanBetween"}, 33 {501, nullptr, "CalculateSpanBetween"},
35 }; 34 };
36 // clang-format on 35 // clang-format on
diff --git a/src/core/hle/service/time/interface.h b/src/core/hle/service/time/interface.h
index 5c63a07f4..4f49e1f07 100644
--- a/src/core/hle/service/time/interface.h
+++ b/src/core/hle/service/time/interface.h
@@ -1,4 +1,4 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -6,14 +6,15 @@
6 6
7#include "core/hle/service/time/time.h" 7#include "core/hle/service/time/time.h"
8 8
9namespace Service::Time { 9namespace Core {
10class System;
11}
10 12
11class SharedMemory; 13namespace Service::Time {
12 14
13class Time final : public Module::Interface { 15class Time final : public Module::Interface {
14public: 16public:
15 explicit Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, 17 explicit Time(std::shared_ptr<Module> time, Core::System& system, const char* name);
16 Core::System& system, const char* name);
17 ~Time() override; 18 ~Time() override;
18}; 19};
19 20
diff --git a/src/core/hle/service/time/local_system_clock_context_writer.h b/src/core/hle/service/time/local_system_clock_context_writer.h
new file mode 100644
index 000000000..7050844c6
--- /dev/null
+++ b/src/core/hle/service/time/local_system_clock_context_writer.h
@@ -0,0 +1,28 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/errors.h"
8#include "core/hle/service/time/system_clock_context_update_callback.h"
9#include "core/hle/service/time/time_sharedmemory.h"
10
11namespace Service::Time::Clock {
12
13class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback {
14public:
15 explicit LocalSystemClockContextWriter(SharedMemory& shared_memory)
16 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {}
17
18protected:
19 ResultCode Update() override {
20 shared_memory.UpdateLocalSystemClockContext(context);
21 return RESULT_SUCCESS;
22 }
23
24private:
25 SharedMemory& shared_memory;
26};
27
28} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/network_system_clock_context_writer.h b/src/core/hle/service/time/network_system_clock_context_writer.h
new file mode 100644
index 000000000..94d8788ff
--- /dev/null
+++ b/src/core/hle/service/time/network_system_clock_context_writer.h
@@ -0,0 +1,28 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/errors.h"
8#include "core/hle/service/time/system_clock_context_update_callback.h"
9#include "core/hle/service/time/time_sharedmemory.h"
10
11namespace Service::Time::Clock {
12
13class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
14public:
15 explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory)
16 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {}
17
18protected:
19 ResultCode Update() override {
20 shared_memory.UpdateNetworkSystemClockContext(context);
21 return RESULT_SUCCESS;
22 }
23
24private:
25 SharedMemory& shared_memory;
26};
27
28} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_local_system_clock_core.h b/src/core/hle/service/time/standard_local_system_clock_core.h
new file mode 100644
index 000000000..8c1882eb1
--- /dev/null
+++ b/src/core/hle/service/time/standard_local_system_clock_core.h
@@ -0,0 +1,17 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/system_clock_core.h"
8
9namespace Service::Time::Clock {
10
11class StandardLocalSystemClockCore final : public SystemClockCore {
12public:
13 explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core)
14 : SystemClockCore{steady_clock_core} {}
15};
16
17} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_network_system_clock_core.h b/src/core/hle/service/time/standard_network_system_clock_core.h
new file mode 100644
index 000000000..3f505c37c
--- /dev/null
+++ b/src/core/hle/service/time/standard_network_system_clock_core.h
@@ -0,0 +1,46 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/clock_types.h"
8#include "core/hle/service/time/steady_clock_core.h"
9#include "core/hle/service/time/system_clock_core.h"
10
11namespace Core {
12class System;
13}
14
15namespace Service::Time::Clock {
16
17class StandardNetworkSystemClockCore final : public SystemClockCore {
18public:
19 explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core)
20 : SystemClockCore{steady_clock_core} {}
21
22 void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) {
23 standard_network_clock_sufficient_accuracy = value;
24 }
25
26 bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) {
27 SystemClockContext context{};
28 if (GetClockContext(system, context) != RESULT_SUCCESS) {
29 return {};
30 }
31
32 s64 span{};
33 if (context.steady_time_point.GetSpanBetween(
34 GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) {
35 return {};
36 }
37
38 return TimeSpanType{span}.nanoseconds <
39 standard_network_clock_sufficient_accuracy.nanoseconds;
40 }
41
42private:
43 TimeSpanType standard_network_clock_sufficient_accuracy{};
44};
45
46} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_steady_clock_core.cpp b/src/core/hle/service/time/standard_steady_clock_core.cpp
new file mode 100644
index 000000000..ca1a783fc
--- /dev/null
+++ b/src/core/hle/service/time/standard_steady_clock_core.cpp
@@ -0,0 +1,26 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/core.h"
6#include "core/core_timing.h"
7#include "core/core_timing_util.h"
8#include "core/hle/service/time/standard_steady_clock_core.h"
9
10namespace Service::Time::Clock {
11
12TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
13 const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
14 Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
15 Core::Timing::CNTFREQ)};
16 TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
17
18 if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {
19 raw_time_point.nanoseconds = cached_raw_time_point.nanoseconds;
20 }
21
22 cached_raw_time_point = raw_time_point;
23 return raw_time_point;
24}
25
26} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_steady_clock_core.h b/src/core/hle/service/time/standard_steady_clock_core.h
new file mode 100644
index 000000000..f56f3fd95
--- /dev/null
+++ b/src/core/hle/service/time/standard_steady_clock_core.h
@@ -0,0 +1,42 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/clock_types.h"
8#include "core/hle/service/time/steady_clock_core.h"
9
10namespace Core {
11class System;
12}
13
14namespace Service::Time::Clock {
15
16class StandardSteadyClockCore final : public SteadyClockCore {
17public:
18 SteadyClockTimePoint GetTimePoint(Core::System& system) override {
19 return {GetCurrentRawTimePoint(system).ToSeconds(), GetClockSourceId()};
20 }
21
22 TimeSpanType GetInternalOffset() const override {
23 return internal_offset;
24 }
25
26 void SetInternalOffset(TimeSpanType value) override {
27 internal_offset = value;
28 }
29
30 TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
31
32 void SetSetupValue(TimeSpanType value) {
33 setup_value = value;
34 }
35
36private:
37 TimeSpanType setup_value{};
38 TimeSpanType internal_offset{};
39 TimeSpanType cached_raw_time_point{};
40};
41
42} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.cpp b/src/core/hle/service/time/standard_user_system_clock_core.cpp
new file mode 100644
index 000000000..8af17091c
--- /dev/null
+++ b/src/core/hle/service/time/standard_user_system_clock_core.cpp
@@ -0,0 +1,77 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "core/core.h"
7#include "core/hle/kernel/writable_event.h"
8#include "core/hle/service/time/standard_local_system_clock_core.h"
9#include "core/hle/service/time/standard_network_system_clock_core.h"
10#include "core/hle/service/time/standard_user_system_clock_core.h"
11
12namespace Service::Time::Clock {
13
14StandardUserSystemClockCore::StandardUserSystemClockCore(
15 StandardLocalSystemClockCore& local_system_clock_core,
16 StandardNetworkSystemClockCore& network_system_clock_core, Core::System& system)
17 : SystemClockCore(local_system_clock_core.GetSteadyClockCore()),
18 local_system_clock_core{local_system_clock_core},
19 network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
20 auto_correction_time{SteadyClockTimePoint::GetRandom()},
21 auto_correction_event{Kernel::WritableEvent::CreateEventPair(
22 system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {}
23
24ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
25 bool value) {
26 if (const ResultCode result{ApplyAutomaticCorrection(system, value)};
27 result != RESULT_SUCCESS) {
28 return result;
29 }
30
31 auto_correction_enabled = value;
32
33 return RESULT_SUCCESS;
34}
35
36ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system,
37 SystemClockContext& context) const {
38 if (const ResultCode result{ApplyAutomaticCorrection(system, false)};
39 result != RESULT_SUCCESS) {
40 return result;
41 }
42
43 return local_system_clock_core.GetClockContext(system, context);
44}
45
46ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext& context) {
47 UNREACHABLE();
48 return ERROR_NOT_IMPLEMENTED;
49}
50
51ResultCode StandardUserSystemClockCore::SetClockContext(const SystemClockContext& context) {
52 UNREACHABLE();
53 return ERROR_NOT_IMPLEMENTED;
54}
55
56ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& system,
57 bool value) const {
58 if (auto_correction_enabled == value) {
59 return RESULT_SUCCESS;
60 }
61
62 if (!network_system_clock_core.IsClockSetup(system)) {
63 return ERROR_UNINITIALIZED_CLOCK;
64 }
65
66 SystemClockContext context{};
67 if (const ResultCode result{network_system_clock_core.GetClockContext(system, context)};
68 result != RESULT_SUCCESS) {
69 return result;
70 }
71
72 local_system_clock_core.SetClockContext(context);
73
74 return RESULT_SUCCESS;
75}
76
77} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.h b/src/core/hle/service/time/standard_user_system_clock_core.h
new file mode 100644
index 000000000..ef3d468b7
--- /dev/null
+++ b/src/core/hle/service/time/standard_user_system_clock_core.h
@@ -0,0 +1,57 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/writable_event.h"
8#include "core/hle/service/time/clock_types.h"
9#include "core/hle/service/time/system_clock_core.h"
10
11namespace Core {
12class System;
13}
14
15namespace Service::Time::Clock {
16
17class StandardLocalSystemClockCore;
18class StandardNetworkSystemClockCore;
19
20class StandardUserSystemClockCore final : public SystemClockCore {
21public:
22 StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core,
23 StandardNetworkSystemClockCore& network_system_clock_core,
24 Core::System& system);
25
26 ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value);
27
28 ResultCode GetClockContext(Core::System& system, SystemClockContext& context) const override;
29
30 bool IsAutomaticCorrectionEnabled() const {
31 return auto_correction_enabled;
32 }
33
34 void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steady_clock_time_point) {
35 auto_correction_time = steady_clock_time_point;
36 }
37
38protected:
39 ResultCode Flush(const SystemClockContext& context) override;
40
41 ResultCode SetClockContext(const SystemClockContext&) override;
42
43 ResultCode ApplyAutomaticCorrection(Core::System& system, bool value) const;
44
45 const SteadyClockTimePoint& GetAutomaticCorrectionUpdatedTime() const {
46 return auto_correction_time;
47 }
48
49private:
50 StandardLocalSystemClockCore& local_system_clock_core;
51 StandardNetworkSystemClockCore& network_system_clock_core;
52 bool auto_correction_enabled{};
53 SteadyClockTimePoint auto_correction_time;
54 Kernel::EventPair auto_correction_event;
55};
56
57} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/steady_clock_core.h b/src/core/hle/service/time/steady_clock_core.h
new file mode 100644
index 000000000..84af3d105
--- /dev/null
+++ b/src/core/hle/service/time/steady_clock_core.h
@@ -0,0 +1,55 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/uuid.h"
8#include "core/hle/service/time/clock_types.h"
9
10namespace Core {
11class System;
12}
13
14namespace Service::Time::Clock {
15
16class SteadyClockCore {
17public:
18 SteadyClockCore() = default;
19
20 const Common::UUID& GetClockSourceId() const {
21 return clock_source_id;
22 }
23
24 void SetClockSourceId(const Common::UUID& value) {
25 clock_source_id = value;
26 }
27
28 virtual TimeSpanType GetInternalOffset() const = 0;
29
30 virtual void SetInternalOffset(TimeSpanType internal_offset) = 0;
31
32 virtual SteadyClockTimePoint GetTimePoint(Core::System& system) = 0;
33
34 virtual TimeSpanType GetCurrentRawTimePoint(Core::System& system) = 0;
35
36 SteadyClockTimePoint GetCurrentTimePoint(Core::System& system) {
37 SteadyClockTimePoint result{GetTimePoint(system)};
38 result.time_point += GetInternalOffset().ToSeconds();
39 return result;
40 }
41
42 bool IsInitialized() const {
43 return is_initialized;
44 }
45
46 void MarkAsInitialized() {
47 is_initialized = true;
48 }
49
50private:
51 Common::UUID clock_source_id{Common::UUID::Generate()};
52 bool is_initialized{};
53};
54
55} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.cpp b/src/core/hle/service/time/system_clock_context_update_callback.cpp
new file mode 100644
index 000000000..5cdb80703
--- /dev/null
+++ b/src/core/hle/service/time/system_clock_context_update_callback.cpp
@@ -0,0 +1,55 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/writable_event.h"
6#include "core/hle/service/time/errors.h"
7#include "core/hle/service/time/system_clock_context_update_callback.h"
8
9namespace Service::Time::Clock {
10
11SystemClockContextUpdateCallback::SystemClockContextUpdateCallback() = default;
12SystemClockContextUpdateCallback::~SystemClockContextUpdateCallback() = default;
13
14bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& value) const {
15 if (has_context) {
16 return context.offset != value.offset ||
17 context.steady_time_point.clock_source_id != value.steady_time_point.clock_source_id;
18 }
19
20 return true;
21}
22
23void SystemClockContextUpdateCallback::RegisterOperationEvent(
24 std::shared_ptr<Kernel::WritableEvent>&& writable_event) {
25 operation_event_list.emplace_back(std::move(writable_event));
26}
27
28void SystemClockContextUpdateCallback::BroadcastOperationEvent() {
29 for (const auto& writable_event : operation_event_list) {
30 writable_event->Signal();
31 }
32}
33
34ResultCode SystemClockContextUpdateCallback::Update(const SystemClockContext& value) {
35 ResultCode result{RESULT_SUCCESS};
36
37 if (NeedUpdate(value)) {
38 context = value;
39 has_context = true;
40
41 result = Update();
42
43 if (result == RESULT_SUCCESS) {
44 BroadcastOperationEvent();
45 }
46 }
47
48 return result;
49}
50
51ResultCode SystemClockContextUpdateCallback::Update() {
52 return RESULT_SUCCESS;
53}
54
55} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h
new file mode 100644
index 000000000..6260de6c3
--- /dev/null
+++ b/src/core/hle/service/time/system_clock_context_update_callback.h
@@ -0,0 +1,43 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <vector>
8
9#include "core/hle/service/time/clock_types.h"
10
11namespace Kernel {
12class WritableEvent;
13}
14
15namespace Service::Time::Clock {
16
17// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
18// This code was released under public domain.
19
20class SystemClockContextUpdateCallback {
21public:
22 SystemClockContextUpdateCallback();
23 ~SystemClockContextUpdateCallback();
24
25 bool NeedUpdate(const SystemClockContext& value) const;
26
27 void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event);
28
29 void BroadcastOperationEvent();
30
31 ResultCode Update(const SystemClockContext& value);
32
33protected:
34 virtual ResultCode Update();
35
36 SystemClockContext context{};
37
38private:
39 bool has_context{};
40 std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list;
41};
42
43} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp
new file mode 100644
index 000000000..1a3ab8cfa
--- /dev/null
+++ b/src/core/hle/service/time/system_clock_core.cpp
@@ -0,0 +1,72 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/service/time/steady_clock_core.h"
6#include "core/hle/service/time/system_clock_context_update_callback.h"
7#include "core/hle/service/time/system_clock_core.h"
8
9namespace Service::Time::Clock {
10
11SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core)
12 : steady_clock_core{steady_clock_core}, is_initialized{} {
13 context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
14}
15
16SystemClockCore ::~SystemClockCore() = default;
17
18ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
19 posix_time = 0;
20
21 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
22
23 SystemClockContext clock_context{};
24 if (const ResultCode result{GetClockContext(system, clock_context)}; result != RESULT_SUCCESS) {
25 return result;
26 }
27
28 if (current_time_point.clock_source_id != clock_context.steady_time_point.clock_source_id) {
29 return ERROR_TIME_MISMATCH;
30 }
31
32 posix_time = clock_context.offset + current_time_point.time_point;
33
34 return RESULT_SUCCESS;
35}
36
37ResultCode SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) {
38 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
39 const SystemClockContext clock_context{posix_time - current_time_point.time_point,
40 current_time_point};
41
42 if (const ResultCode result{SetClockContext(clock_context)}; result != RESULT_SUCCESS) {
43 return result;
44 }
45 return Flush(clock_context);
46}
47
48ResultCode SystemClockCore::Flush(const SystemClockContext& context) {
49 if (!system_clock_context_update_callback) {
50 return RESULT_SUCCESS;
51 }
52 return system_clock_context_update_callback->Update(context);
53}
54
55ResultCode SystemClockCore::SetSystemClockContext(const SystemClockContext& context) {
56 if (const ResultCode result{SetClockContext(context)}; result != RESULT_SUCCESS) {
57 return result;
58 }
59 return Flush(context);
60}
61
62bool SystemClockCore::IsClockSetup(Core::System& system) const {
63 SystemClockContext value{};
64 if (GetClockContext(system, value) == RESULT_SUCCESS) {
65 const SteadyClockTimePoint steady_clock_time_point{
66 steady_clock_core.GetCurrentTimePoint(system)};
67 return steady_clock_time_point.clock_source_id == value.steady_time_point.clock_source_id;
68 }
69 return {};
70}
71
72} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_core.h b/src/core/hle/service/time/system_clock_core.h
new file mode 100644
index 000000000..54407a6c5
--- /dev/null
+++ b/src/core/hle/service/time/system_clock_core.h
@@ -0,0 +1,71 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "core/hle/service/time/clock_types.h"
9
10namespace Core {
11class System;
12}
13
14namespace Service::Time::Clock {
15
16class SteadyClockCore;
17class SystemClockContextUpdateCallback;
18
19// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
20// This code was released under public domain.
21
22class SystemClockCore {
23public:
24 explicit SystemClockCore(SteadyClockCore& steady_clock_core);
25 ~SystemClockCore();
26
27 SteadyClockCore& GetSteadyClockCore() const {
28 return steady_clock_core;
29 }
30
31 ResultCode GetCurrentTime(Core::System& system, s64& posix_time) const;
32
33 ResultCode SetCurrentTime(Core::System& system, s64 posix_time);
34
35 virtual ResultCode GetClockContext([[maybe_unused]] Core::System& system,
36 SystemClockContext& value) const {
37 value = context;
38 return RESULT_SUCCESS;
39 }
40
41 virtual ResultCode SetClockContext(const SystemClockContext& value) {
42 context = value;
43 return RESULT_SUCCESS;
44 }
45
46 virtual ResultCode Flush(const SystemClockContext& context);
47
48 void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) {
49 system_clock_context_update_callback = std::move(callback);
50 }
51
52 ResultCode SetSystemClockContext(const SystemClockContext& context);
53
54 bool IsInitialized() const {
55 return is_initialized;
56 }
57
58 void MarkAsInitialized() {
59 is_initialized = true;
60 }
61
62 bool IsClockSetup(Core::System& system) const;
63
64private:
65 SteadyClockCore& steady_clock_core;
66 SystemClockContext context{};
67 bool is_initialized{};
68 std::shared_ptr<SystemClockContextUpdateCallback> system_clock_context_update_callback;
69};
70
71} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.cpp b/src/core/hle/service/time/tick_based_steady_clock_core.cpp
new file mode 100644
index 000000000..c77b98189
--- /dev/null
+++ b/src/core/hle/service/time/tick_based_steady_clock_core.cpp
@@ -0,0 +1,24 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/core.h"
6#include "core/core_timing.h"
7#include "core/core_timing_util.h"
8#include "core/hle/service/time/tick_based_steady_clock_core.h"
9
10namespace Service::Time::Clock {
11
12SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
13 const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
14 Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
15 Core::Timing::CNTFREQ)};
16
17 return {ticks_time_span.ToSeconds(), GetClockSourceId()};
18}
19
20TimeSpanType TickBasedSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
21 return TimeSpanType::FromSeconds(GetTimePoint(system).time_point);
22}
23
24} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.h b/src/core/hle/service/time/tick_based_steady_clock_core.h
new file mode 100644
index 000000000..1a5a53fd7
--- /dev/null
+++ b/src/core/hle/service/time/tick_based_steady_clock_core.h
@@ -0,0 +1,29 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/time/clock_types.h"
8#include "core/hle/service/time/steady_clock_core.h"
9
10namespace Core {
11class System;
12}
13
14namespace Service::Time::Clock {
15
16class TickBasedSteadyClockCore final : public SteadyClockCore {
17public:
18 TimeSpanType GetInternalOffset() const override {
19 return {};
20 }
21
22 void SetInternalOffset(TimeSpanType internal_offset) override {}
23
24 SteadyClockTimePoint GetTimePoint(Core::System& system) override;
25
26 TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
27};
28
29} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 6ee77c5f9..8ef4efcef 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -1,9 +1,7 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <chrono>
6#include <ctime>
7#include "common/logging/log.h" 5#include "common/logging/log.h"
8#include "core/core.h" 6#include "core/core.h"
9#include "core/core_timing.h" 7#include "core/core_timing.h"
@@ -11,429 +9,321 @@
11#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
12#include "core/hle/kernel/client_port.h" 10#include "core/hle/kernel/client_port.h"
13#include "core/hle/kernel/client_session.h" 11#include "core/hle/kernel/client_session.h"
12#include "core/hle/kernel/scheduler.h"
14#include "core/hle/service/time/interface.h" 13#include "core/hle/service/time/interface.h"
15#include "core/hle/service/time/time.h" 14#include "core/hle/service/time/time.h"
16#include "core/hle/service/time/time_sharedmemory.h" 15#include "core/hle/service/time/time_sharedmemory.h"
17#include "core/settings.h" 16#include "core/hle/service/time/time_zone_service.h"
18 17
19namespace Service::Time { 18namespace Service::Time {
20 19
21static std::chrono::seconds GetSecondsSinceEpoch() {
22 return std::chrono::duration_cast<std::chrono::seconds>(
23 std::chrono::system_clock::now().time_since_epoch()) +
24 Settings::values.custom_rtc_differential;
25}
26
27static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time,
28 CalendarAdditionalInfo& additional_info,
29 [[maybe_unused]] const TimeZoneRule& /*rule*/) {
30 const std::time_t time(posix_time);
31 const std::tm* tm = std::localtime(&time);
32 if (tm == nullptr) {
33 calendar_time = {};
34 additional_info = {};
35 return;
36 }
37 calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900);
38 calendar_time.month = static_cast<u8>(tm->tm_mon + 1);
39 calendar_time.day = static_cast<u8>(tm->tm_mday);
40 calendar_time.hour = static_cast<u8>(tm->tm_hour);
41 calendar_time.minute = static_cast<u8>(tm->tm_min);
42 calendar_time.second = static_cast<u8>(tm->tm_sec);
43
44 additional_info.day_of_week = tm->tm_wday;
45 additional_info.day_of_year = tm->tm_yday;
46 std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC"));
47 additional_info.utc_offset = 0;
48}
49
50static u64 CalendarToPosix(const CalendarTime& calendar_time,
51 [[maybe_unused]] const TimeZoneRule& /*rule*/) {
52 std::tm time{};
53 time.tm_year = calendar_time.year - 1900;
54 time.tm_mon = calendar_time.month - 1;
55 time.tm_mday = calendar_time.day;
56
57 time.tm_hour = calendar_time.hour;
58 time.tm_min = calendar_time.minute;
59 time.tm_sec = calendar_time.second;
60
61 std::time_t epoch_time = std::mktime(&time);
62 return static_cast<u64>(epoch_time);
63}
64
65enum class ClockContextType {
66 StandardSteady,
67 StandardUserSystem,
68 StandardNetworkSystem,
69 StandardLocalSystem,
70};
71
72class ISystemClock final : public ServiceFramework<ISystemClock> { 20class ISystemClock final : public ServiceFramework<ISystemClock> {
73public: 21public:
74 ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory, 22 ISystemClock(Clock::SystemClockCore& clock_core)
75 ClockContextType clock_type) 23 : ServiceFramework("ISystemClock"), clock_core{clock_core} {
76 : ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) {
77 // clang-format off 24 // clang-format off
78 static const FunctionInfo functions[] = { 25 static const FunctionInfo functions[] = {
79 {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, 26 {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
80 {1, nullptr, "SetCurrentTime"}, 27 {1, nullptr, "SetCurrentTime"},
81 {2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"}, 28 {2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
82 {3, nullptr, "SetSystemClockContext"}, 29 {3, nullptr, "SetSystemClockContext"},
83 {4, nullptr, "GetOperationEventReadableHandle"}, 30 {4, nullptr, "GetOperationEventReadableHandle"},
84 }; 31 };
85 // clang-format on 32 // clang-format on
86 33
87 RegisterHandlers(functions); 34 RegisterHandlers(functions);
88 UpdateSharedMemoryContext(system_clock_context);
89 } 35 }
90 36
91private: 37private:
92 void GetCurrentTime(Kernel::HLERequestContext& ctx) { 38 void GetCurrentTime(Kernel::HLERequestContext& ctx) {
93 const s64 time_since_epoch{GetSecondsSinceEpoch().count()};
94 LOG_DEBUG(Service_Time, "called"); 39 LOG_DEBUG(Service_Time, "called");
95 40
41 if (!clock_core.IsInitialized()) {
42 IPC::ResponseBuilder rb{ctx, 2};
43 rb.Push(ERROR_UNINITIALIZED_CLOCK);
44 return;
45 }
46
47 s64 posix_time{};
48 if (const ResultCode result{
49 clock_core.GetCurrentTime(Core::System::GetInstance(), posix_time)};
50 result != RESULT_SUCCESS) {
51 IPC::ResponseBuilder rb{ctx, 2};
52 rb.Push(result);
53 return;
54 }
55
96 IPC::ResponseBuilder rb{ctx, 4}; 56 IPC::ResponseBuilder rb{ctx, 4};
97 rb.Push(RESULT_SUCCESS); 57 rb.Push(RESULT_SUCCESS);
98 rb.Push<u64>(time_since_epoch); 58 rb.Push<s64>(posix_time);
99 } 59 }
100 60
101 void GetSystemClockContext(Kernel::HLERequestContext& ctx) { 61 void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
102 LOG_WARNING(Service_Time, "(STUBBED) called"); 62 LOG_DEBUG(Service_Time, "called");
63
64 if (!clock_core.IsInitialized()) {
65 IPC::ResponseBuilder rb{ctx, 2};
66 rb.Push(ERROR_UNINITIALIZED_CLOCK);
67 return;
68 }
103 69
104 // TODO(ogniK): This should be updated periodically however since we have it stubbed we'll 70 Clock::SystemClockContext system_clock_context{};
105 // only update when we get a new context 71 if (const ResultCode result{
106 UpdateSharedMemoryContext(system_clock_context); 72 clock_core.GetClockContext(Core::System::GetInstance(), system_clock_context)};
73 result != RESULT_SUCCESS) {
74 IPC::ResponseBuilder rb{ctx, 2};
75 rb.Push(result);
76 return;
77 }
107 78
108 IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; 79 IPC::ResponseBuilder rb{ctx, sizeof(Clock::SystemClockContext) / 4 + 2};
109 rb.Push(RESULT_SUCCESS); 80 rb.Push(RESULT_SUCCESS);
110 rb.PushRaw(system_clock_context); 81 rb.PushRaw(system_clock_context);
111 } 82 }
112 83
113 void UpdateSharedMemoryContext(const SystemClockContext& clock_context) { 84 Clock::SystemClockCore& clock_core;
114 switch (clock_type) {
115 case ClockContextType::StandardLocalSystem:
116 shared_memory->SetStandardLocalSystemClockContext(clock_context);
117 break;
118 case ClockContextType::StandardNetworkSystem:
119 shared_memory->SetStandardNetworkSystemClockContext(clock_context);
120 break;
121 }
122 }
123
124 SystemClockContext system_clock_context{};
125 std::shared_ptr<Service::Time::SharedMemory> shared_memory;
126 ClockContextType clock_type;
127}; 85};
128 86
129class ISteadyClock final : public ServiceFramework<ISteadyClock> { 87class ISteadyClock final : public ServiceFramework<ISteadyClock> {
130public: 88public:
131 ISteadyClock(std::shared_ptr<SharedMemory> shared_memory, Core::System& system) 89 ISteadyClock(Clock::SteadyClockCore& clock_core)
132 : ServiceFramework("ISteadyClock"), shared_memory(shared_memory), system(system) { 90 : ServiceFramework("ISteadyClock"), clock_core{clock_core} {
133 static const FunctionInfo functions[] = { 91 static const FunctionInfo functions[] = {
134 {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, 92 {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
135 }; 93 };
136 RegisterHandlers(functions); 94 RegisterHandlers(functions);
137
138 shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint());
139 } 95 }
140 96
141private: 97private:
142 void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { 98 void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
143 LOG_DEBUG(Service_Time, "called"); 99 LOG_DEBUG(Service_Time, "called");
144 100
145 const auto time_point = GetCurrentTimePoint(); 101 if (!clock_core.IsInitialized()) {
146 // TODO(ogniK): This should be updated periodically 102 IPC::ResponseBuilder rb{ctx, 2};
147 shared_memory->SetStandardSteadyClockTimepoint(time_point); 103 rb.Push(ERROR_UNINITIALIZED_CLOCK);
104 return;
105 }
148 106
149 IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; 107 const Clock::SteadyClockTimePoint time_point{
108 clock_core.GetCurrentTimePoint(Core::System::GetInstance())};
109 IPC::ResponseBuilder rb{ctx, (sizeof(Clock::SteadyClockTimePoint) / 4) + 2};
150 rb.Push(RESULT_SUCCESS); 110 rb.Push(RESULT_SUCCESS);
151 rb.PushRaw(time_point); 111 rb.PushRaw(time_point);
152 } 112 }
153 113
154 SteadyClockTimePoint GetCurrentTimePoint() const { 114 Clock::SteadyClockCore& clock_core;
155 const auto& core_timing = system.CoreTiming();
156 const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
157 return {static_cast<u64_le>(ms.count() / 1000), {}};
158 }
159
160 std::shared_ptr<SharedMemory> shared_memory;
161 Core::System& system;
162}; 115};
163 116
164class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { 117ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
165public: 118 Kernel::Thread* thread, Clock::SystemClockContext user_context,
166 ITimeZoneService() : ServiceFramework("ITimeZoneService") { 119 Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) {
167 // clang-format off
168 static const FunctionInfo functions[] = {
169 {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
170 {1, nullptr, "SetDeviceLocationName"},
171 {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
172 {3, nullptr, "LoadLocationNameList"},
173 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
174 {5, nullptr, "GetTimeZoneRuleVersion"},
175 {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
176 {7, nullptr, "SetDeviceLocationNameWithTimeZoneRule"},
177 {8, nullptr, "ParseTimeZoneBinary"},
178 {20, nullptr, "GetDeviceLocationNameOperationEventReadableHandle"},
179 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
180 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
181 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
182 {202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
183 };
184 // clang-format on
185
186 RegisterHandlers(functions);
187 }
188 120
189private: 121 auto& time_manager{module->GetTimeManager()};
190 LocationName location_name{"UTC"};
191 TimeZoneRule my_time_zone_rule{};
192 122
193 void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { 123 clock_snapshot.is_automatic_correction_enabled =
194 LOG_DEBUG(Service_Time, "called"); 124 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
125 clock_snapshot.user_context = user_context;
126 clock_snapshot.network_context = network_context;
195 127
196 IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; 128 if (const ResultCode result{
197 rb.Push(RESULT_SUCCESS); 129 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName(
198 rb.PushRaw(location_name); 130 clock_snapshot.location_name)};
131 result != RESULT_SUCCESS) {
132 return result;
199 } 133 }
200 134
201 void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) { 135 const auto current_time_point{
202 LOG_WARNING(Service_Time, "(STUBBED) called"); 136 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(Core::System::GetInstance())};
203 137 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime(
204 IPC::ResponseBuilder rb{ctx, 3}; 138 clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)};
205 rb.Push(RESULT_SUCCESS); 139 result != RESULT_SUCCESS) {
206 rb.Push<u32>(0); 140 return result;
207 } 141 }
208 142
209 void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { 143 TimeZone::CalendarInfo userCalendarInfo{};
210 LOG_WARNING(Service_Time, "(STUBBED) called"); 144 if (const ResultCode result{
211 145 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
212 ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule)); 146 clock_snapshot.user_time, userCalendarInfo)};
213 147 result != RESULT_SUCCESS) {
214 IPC::ResponseBuilder rb{ctx, 2}; 148 return result;
215 rb.Push(RESULT_SUCCESS);
216 } 149 }
217 150
218 void ToCalendarTime(Kernel::HLERequestContext& ctx) { 151 clock_snapshot.user_calendar_time = userCalendarInfo.time;
219 IPC::RequestParser rp{ctx}; 152 clock_snapshot.user_calendar_additional_time = userCalendarInfo.additiona_info;
220 const u64 posix_time = rp.Pop<u64>();
221 LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
222
223 TimeZoneRule time_zone_rule{};
224 auto buffer = ctx.ReadBuffer();
225 std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
226 153
227 CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; 154 if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time, current_time_point,
228 CalendarAdditionalInfo additional_info{}; 155 clock_snapshot.network_context) != RESULT_SUCCESS) {
229 156 clock_snapshot.network_time = 0;
230 PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule);
231
232 IPC::ResponseBuilder rb{ctx, 10};
233 rb.Push(RESULT_SUCCESS);
234 rb.PushRaw(calendar_time);
235 rb.PushRaw(additional_info);
236 }
237
238 void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
239 IPC::RequestParser rp{ctx};
240 const u64 posix_time = rp.Pop<u64>();
241 LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
242
243 CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
244 CalendarAdditionalInfo additional_info{};
245
246 PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule);
247
248 IPC::ResponseBuilder rb{ctx, 10};
249 rb.Push(RESULT_SUCCESS);
250 rb.PushRaw(calendar_time);
251 rb.PushRaw(additional_info);
252 } 157 }
253 158
254 void ToPosixTime(Kernel::HLERequestContext& ctx) { 159 TimeZone::CalendarInfo networkCalendarInfo{};
255 // TODO(ogniK): Figure out how to handle multiple times 160 if (const ResultCode result{
256 LOG_WARNING(Service_Time, "(STUBBED) called"); 161 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
257 162 clock_snapshot.network_time, networkCalendarInfo)};
258 IPC::RequestParser rp{ctx}; 163 result != RESULT_SUCCESS) {
259 auto calendar_time = rp.PopRaw<CalendarTime>(); 164 return result;
260 auto posix_time = CalendarToPosix(calendar_time, {});
261
262 IPC::ResponseBuilder rb{ctx, 3};
263 rb.Push(RESULT_SUCCESS);
264 rb.PushRaw<u32>(1); // Amount of times we're returning
265 ctx.WriteBuffer(&posix_time, sizeof(u64));
266 } 165 }
267 166
268 void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { 167 clock_snapshot.network_calendar_time = networkCalendarInfo.time;
269 LOG_WARNING(Service_Time, "(STUBBED) called"); 168 clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additiona_info;
270 169 clock_snapshot.type = type;
271 IPC::RequestParser rp{ctx};
272 auto calendar_time = rp.PopRaw<CalendarTime>();
273 auto posix_time = CalendarToPosix(calendar_time, {});
274 170
275 IPC::ResponseBuilder rb{ctx, 3}; 171 return RESULT_SUCCESS;
276 rb.Push(RESULT_SUCCESS); 172}
277 rb.PushRaw<u32>(1); // Amount of times we're returning
278 ctx.WriteBuffer(&posix_time, sizeof(u64));
279 }
280};
281 173
282void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { 174void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
283 LOG_DEBUG(Service_Time, "called"); 175 LOG_DEBUG(Service_Time, "called");
284
285 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 176 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
286 rb.Push(RESULT_SUCCESS); 177 rb.Push(RESULT_SUCCESS);
287 rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem); 178 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore());
288} 179}
289 180
290void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { 181void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
291 LOG_DEBUG(Service_Time, "called"); 182 LOG_DEBUG(Service_Time, "called");
292
293 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 183 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
294 rb.Push(RESULT_SUCCESS); 184 rb.Push(RESULT_SUCCESS);
295 rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem); 185 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore());
296} 186}
297 187
298void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { 188void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
299 LOG_DEBUG(Service_Time, "called"); 189 LOG_DEBUG(Service_Time, "called");
300
301 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 190 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
302 rb.Push(RESULT_SUCCESS); 191 rb.Push(RESULT_SUCCESS);
303 rb.PushIpcInterface<ISteadyClock>(shared_memory, system); 192 rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore());
304} 193}
305 194
306void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { 195void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
307 LOG_DEBUG(Service_Time, "called"); 196 LOG_DEBUG(Service_Time, "called");
308
309 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 197 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
310 rb.Push(RESULT_SUCCESS); 198 rb.Push(RESULT_SUCCESS);
311 rb.PushIpcInterface<ITimeZoneService>(); 199 rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager());
312} 200}
313 201
314void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { 202void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
315 LOG_DEBUG(Service_Time, "called"); 203 LOG_DEBUG(Service_Time, "called");
316
317 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 204 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
318 rb.Push(RESULT_SUCCESS); 205 rb.Push(RESULT_SUCCESS);
319 rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem); 206 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore());
320} 207}
321 208
322void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { 209void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
210 Kernel::HLERequestContext& ctx) {
323 LOG_DEBUG(Service_Time, "called"); 211 LOG_DEBUG(Service_Time, "called");
212 auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()};
213 IPC::ResponseBuilder rb{ctx, 3};
214 rb.Push(RESULT_SUCCESS);
215 rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
216}
324 217
325 IPC::RequestParser rp{ctx}; 218void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) {
326 const auto initial_type = rp.PopRaw<u8>(); 219 LOG_DEBUG(Service_Time, "called");
327 220
328 const s64 time_since_epoch{GetSecondsSinceEpoch().count()}; 221 auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()};
329 const std::time_t time(time_since_epoch); 222 if (!steady_clock_core.IsInitialized()) {
330 const std::tm* tm = std::localtime(&time);
331 if (tm == nullptr) {
332 LOG_ERROR(Service_Time, "tm is a nullptr");
333 IPC::ResponseBuilder rb{ctx, 2}; 223 IPC::ResponseBuilder rb{ctx, 2};
334 rb.Push(RESULT_UNKNOWN); // TODO(ogniK): Find appropriate error code 224 rb.Push(ERROR_UNINITIALIZED_CLOCK);
335 return; 225 return;
336 } 226 }
337 227
338 const auto& core_timing = system.CoreTiming(); 228 IPC::RequestParser rp{ctx};
339 const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); 229 const auto context{rp.PopRaw<Clock::SystemClockContext>()};
340 const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), {}}; 230 const auto current_time_point{
341 231 steady_clock_core.GetCurrentTimePoint(Core::System::GetInstance())};
342 CalendarTime calendar_time{}; 232
343 calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900); 233 if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) {
344 calendar_time.month = static_cast<u8>(tm->tm_mon + 1); 234 const auto ticks{Clock::TimeSpanType::FromTicks(
345 calendar_time.day = static_cast<u8>(tm->tm_mday); 235 Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
346 calendar_time.hour = static_cast<u8>(tm->tm_hour); 236 Core::Timing::CNTFREQ)};
347 calendar_time.minute = static_cast<u8>(tm->tm_min); 237 const s64 base_time_point{context.offset + current_time_point.time_point -
348 calendar_time.second = static_cast<u8>(tm->tm_sec); 238 ticks.ToSeconds()};
239 IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
240 rb.Push(RESULT_SUCCESS);
241 rb.PushRaw(base_time_point);
242 return;
243 }
349 244
350 ClockSnapshot clock_snapshot{}; 245 IPC::ResponseBuilder rb{ctx, 2};
351 clock_snapshot.system_posix_time = time_since_epoch; 246 rb.Push(ERROR_TIME_MISMATCH);
352 clock_snapshot.network_posix_time = time_since_epoch; 247}
353 clock_snapshot.system_calendar_time = calendar_time;
354 clock_snapshot.network_calendar_time = calendar_time;
355 248
356 CalendarAdditionalInfo additional_info{}; 249void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
357 PosixToCalendar(time_since_epoch, calendar_time, additional_info, {}); 250 LOG_DEBUG(Service_Time, "called");
251 IPC::RequestParser rp{ctx};
252 const auto type{rp.PopRaw<u8>()};
358 253
359 clock_snapshot.system_calendar_info = additional_info; 254 Clock::SystemClockContext user_context{};
360 clock_snapshot.network_calendar_info = additional_info; 255 if (const ResultCode result{
256 module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(
257 Core::System::GetInstance(), user_context)};
258 result != RESULT_SUCCESS) {
259 IPC::ResponseBuilder rb{ctx, 2};
260 rb.Push(result);
261 return;
262 }
263 Clock::SystemClockContext network_context{};
264 if (const ResultCode result{
265 module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
266 Core::System::GetInstance(), network_context)};
267 result != RESULT_SUCCESS) {
268 IPC::ResponseBuilder rb{ctx, 2};
269 rb.Push(result);
270 return;
271 }
361 272
362 clock_snapshot.steady_clock_timepoint = steady_clock_time_point; 273 Clock::ClockSnapshot clock_snapshot{};
363 clock_snapshot.location_name = LocationName{"UTC"}; 274 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal(
364 clock_snapshot.clock_auto_adjustment_enabled = 1; 275 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
365 clock_snapshot.type = initial_type; 276 result != RESULT_SUCCESS) {
277 IPC::ResponseBuilder rb{ctx, 2};
278 rb.Push(result);
279 return;
280 }
366 281
367 IPC::ResponseBuilder rb{ctx, 2}; 282 IPC::ResponseBuilder rb{ctx, 2};
368 rb.Push(RESULT_SUCCESS); 283 rb.Push(RESULT_SUCCESS);
369 ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot)); 284 ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
370} 285}
371 286
372void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( 287void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
373 Kernel::HLERequestContext& ctx) {
374 LOG_DEBUG(Service_Time, "called"); 288 LOG_DEBUG(Service_Time, "called");
375
376 IPC::RequestParser rp{ctx}; 289 IPC::RequestParser rp{ctx};
377 const auto snapshot_a = rp.PopRaw<ClockSnapshot>(); 290 const auto type{rp.PopRaw<u8>()};
378 const auto snapshot_b = rp.PopRaw<ClockSnapshot>(); 291 rp.AlignWithPadding();
379 const u64 difference = 292
380 snapshot_b.user_clock_context.offset - snapshot_a.user_clock_context.offset; 293 const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
294 const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
381 295
382 IPC::ResponseBuilder rb{ctx, 4}; 296 Clock::ClockSnapshot clock_snapshot{};
297 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal(
298 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
299 result != RESULT_SUCCESS) {
300 IPC::ResponseBuilder rb{ctx, 2};
301 rb.Push(result);
302 return;
303 }
304
305 IPC::ResponseBuilder rb{ctx, 2};
383 rb.Push(RESULT_SUCCESS); 306 rb.Push(RESULT_SUCCESS);
384 rb.PushRaw<u64>(difference); 307 ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
385} 308}
386 309
387void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { 310void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
388 LOG_DEBUG(Service_Time, "called"); 311 LOG_DEBUG(Service_Time, "called");
389 IPC::ResponseBuilder rb{ctx, 2, 1}; 312 IPC::ResponseBuilder rb{ctx, 2, 1};
390 rb.Push(RESULT_SUCCESS); 313 rb.Push(RESULT_SUCCESS);
391 rb.PushCopyObjects(shared_memory->GetSharedMemoryHolder()); 314 rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder());
392}
393
394void Module::Interface::IsStandardUserSystemClockAutomaticCorrectionEnabled(
395 Kernel::HLERequestContext& ctx) {
396 // ogniK(TODO): When clock contexts are implemented, the value should be read from the context
397 // instead of our shared memory holder
398 LOG_DEBUG(Service_Time, "called");
399
400 IPC::ResponseBuilder rb{ctx, 3};
401 rb.Push(RESULT_SUCCESS);
402 rb.Push<u8>(shared_memory->GetStandardUserSystemClockAutomaticCorrectionEnabled());
403}
404
405void Module::Interface::SetStandardUserSystemClockAutomaticCorrectionEnabled(
406 Kernel::HLERequestContext& ctx) {
407 IPC::RequestParser rp{ctx};
408 const auto enabled = rp.Pop<u8>();
409
410 LOG_WARNING(Service_Time, "(PARTIAL IMPLEMENTATION) called");
411
412 // TODO(ogniK): Update clock contexts and correct timespans
413
414 shared_memory->SetStandardUserSystemClockAutomaticCorrectionEnabled(enabled > 0);
415 IPC::ResponseBuilder rb{ctx, 2};
416 rb.Push(RESULT_SUCCESS);
417} 315}
418 316
419Module::Interface::Interface(std::shared_ptr<Module> time, 317Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name)
420 std::shared_ptr<SharedMemory> shared_memory, Core::System& system, 318 : ServiceFramework(name), module{std::move(module)}, system{system} {}
421 const char* name)
422 : ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)),
423 system(system) {}
424 319
425Module::Interface::~Interface() = default; 320Module::Interface::~Interface() = default;
426 321
427void InstallInterfaces(Core::System& system) { 322void InstallInterfaces(Core::System& system) {
428 auto time = std::make_shared<Module>(); 323 auto module{std::make_shared<Module>(system)};
429 auto shared_mem = std::make_shared<SharedMemory>(system); 324 std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager());
430 325 std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager());
431 std::make_shared<Time>(time, shared_mem, system, "time:a") 326 std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager());
432 ->InstallAsService(system.ServiceManager());
433 std::make_shared<Time>(time, shared_mem, system, "time:s")
434 ->InstallAsService(system.ServiceManager());
435 std::make_shared<Time>(std::move(time), shared_mem, system, "time:u")
436 ->InstallAsService(system.ServiceManager());
437} 327}
438 328
439} // namespace Service::Time 329} // namespace Service::Time
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index c32d32860..aadc2df60 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -4,84 +4,23 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include "common/common_funcs.h"
9#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8#include "core/hle/service/time/clock_types.h"
9#include "core/hle/service/time/time_manager.h"
10 10
11namespace Service::Time { 11namespace Core {
12 12class System;
13class SharedMemory; 13}
14
15struct LocationName {
16 std::array<u8, 0x24> name;
17};
18static_assert(sizeof(LocationName) == 0x24, "LocationName is incorrect size");
19
20struct CalendarTime {
21 u16_le year;
22 u8 month; // Starts at 1
23 u8 day; // Starts at 1
24 u8 hour;
25 u8 minute;
26 u8 second;
27};
28static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size");
29
30struct CalendarAdditionalInfo {
31 u32_le day_of_week;
32 u32_le day_of_year;
33 std::array<u8, 8> name;
34 u8 is_dst;
35 s32_le utc_offset;
36};
37static_assert(sizeof(CalendarAdditionalInfo) == 0x18,
38 "CalendarAdditionalInfo structure has incorrect size");
39
40// TODO(mailwl) RE this structure
41struct TimeZoneRule {
42 INSERT_PADDING_BYTES(0x4000);
43};
44
45struct SteadyClockTimePoint {
46 using SourceID = std::array<u8, 16>;
47 14
48 u64_le value; 15namespace Service::Time {
49 SourceID source_id;
50};
51static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
52
53struct SystemClockContext {
54 u64_le offset;
55 SteadyClockTimePoint time_point;
56};
57static_assert(sizeof(SystemClockContext) == 0x20,
58 "SystemClockContext structure has incorrect size");
59
60struct ClockSnapshot {
61 SystemClockContext user_clock_context;
62 SystemClockContext network_clock_context;
63 s64_le system_posix_time;
64 s64_le network_posix_time;
65 CalendarTime system_calendar_time;
66 CalendarTime network_calendar_time;
67 CalendarAdditionalInfo system_calendar_info;
68 CalendarAdditionalInfo network_calendar_info;
69 SteadyClockTimePoint steady_clock_timepoint;
70 LocationName location_name;
71 u8 clock_auto_adjustment_enabled;
72 u8 type;
73 u8 version;
74 INSERT_PADDING_BYTES(1);
75};
76static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size");
77 16
78class Module final { 17class Module final {
79public: 18public:
19 Module(Core::System& system) : time_manager{system} {}
20
80 class Interface : public ServiceFramework<Interface> { 21 class Interface : public ServiceFramework<Interface> {
81 public: 22 public:
82 explicit Interface(std::shared_ptr<Module> time, 23 explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name);
83 std::shared_ptr<SharedMemory> shared_memory, Core::System& system,
84 const char* name);
85 ~Interface() override; 24 ~Interface() override;
86 25
87 void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); 26 void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
@@ -89,17 +28,29 @@ public:
89 void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); 28 void GetStandardSteadyClock(Kernel::HLERequestContext& ctx);
90 void GetTimeZoneService(Kernel::HLERequestContext& ctx); 29 void GetTimeZoneService(Kernel::HLERequestContext& ctx);
91 void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); 30 void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx);
31 void IsStandardNetworkSystemClockAccuracySufficient(Kernel::HLERequestContext& ctx);
32 void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
92 void GetClockSnapshot(Kernel::HLERequestContext& ctx); 33 void GetClockSnapshot(Kernel::HLERequestContext& ctx);
93 void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); 34 void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx);
94 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); 35 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
95 void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); 36
96 void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); 37 private:
38 ResultCode GetClockSnapshotFromSystemClockContextInternal(
39 Kernel::Thread* thread, Clock::SystemClockContext user_context,
40 Clock::SystemClockContext network_context, u8 type,
41 Clock::ClockSnapshot& cloc_snapshot);
97 42
98 protected: 43 protected:
99 std::shared_ptr<Module> time; 44 std::shared_ptr<Module> module;
100 std::shared_ptr<SharedMemory> shared_memory;
101 Core::System& system; 45 Core::System& system;
102 }; 46 };
47
48 TimeManager& GetTimeManager() {
49 return time_manager;
50 }
51
52private:
53 TimeManager time_manager;
103}; 54};
104 55
105/// Registers all Time services with the specified service manager. 56/// Registers all Time services with the specified service manager.
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
new file mode 100644
index 000000000..9d6c55865
--- /dev/null
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -0,0 +1,137 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <chrono>
6#include <ctime>
7
8#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
9#include "core/hle/service/time/local_system_clock_context_writer.h"
10#include "core/hle/service/time/network_system_clock_context_writer.h"
11#include "core/hle/service/time/time_manager.h"
12#include "core/settings.h"
13
14namespace Service::Time {
15
16constexpr Clock::TimeSpanType standard_network_clock_accuracy{0x0009356907420000ULL};
17
18static std::chrono::seconds GetSecondsSinceEpoch() {
19 return std::chrono::duration_cast<std::chrono::seconds>(
20 std::chrono::system_clock::now().time_since_epoch()) +
21 Settings::values.custom_rtc_differential;
22}
23
24static s64 GetExternalRtcValue() {
25 return GetSecondsSinceEpoch().count();
26}
27
28TimeManager::TimeManager(Core::System& system)
29 : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
30 standard_network_system_clock_core{standard_steady_clock_core},
31 standard_user_system_clock_core{standard_local_system_clock_core,
32 standard_network_system_clock_core, system},
33 ephemeral_network_system_clock_core{tick_based_steady_clock_core},
34 local_system_clock_context_writer{
35 std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
36 network_system_clock_context_writer{
37 std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
38 ephemeral_network_system_clock_context_writer{
39 std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
40 time_zone_content_manager{*this, system} {
41
42 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
43 SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
44 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
45 SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
46 SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
47 SetupEphemeralNetworkSystemClock();
48}
49
50TimeManager::~TimeManager() = default;
51
52void TimeManager::SetupTimeZoneManager(std::string location_name,
53 Clock::SteadyClockTimePoint time_zone_updated_time_point,
54 std::size_t total_location_name_count,
55 u128 time_zone_rule_version,
56 FileSys::VirtualFile& vfs_file) {
57 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
58 location_name, vfs_file) != RESULT_SUCCESS) {
59 UNREACHABLE();
60 return;
61 }
62
63 time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
64 time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
65 total_location_name_count);
66 time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version);
67 time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
68}
69
70void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
71 Clock::TimeSpanType setup_value,
72 Clock::TimeSpanType internal_offset,
73 bool is_rtc_reset_detected) {
74 standard_steady_clock_core.SetClockSourceId(clock_source_id);
75 standard_steady_clock_core.SetSetupValue(setup_value);
76 standard_steady_clock_core.SetInternalOffset(internal_offset);
77 standard_steady_clock_core.MarkAsInitialized();
78
79 const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)};
80 shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point);
81}
82
83void TimeManager::SetupStandardLocalSystemClock(Core::System& system,
84 Clock::SystemClockContext clock_context,
85 s64 posix_time) {
86 standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer);
87
88 const auto current_time_point{
89 standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)};
90 if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
91 standard_local_system_clock_core.SetSystemClockContext(clock_context);
92 } else {
93 if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) {
94 UNREACHABLE();
95 return;
96 }
97 }
98
99 standard_local_system_clock_core.MarkAsInitialized();
100}
101
102void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
103 Clock::TimeSpanType sufficient_accuracy) {
104 standard_network_system_clock_core.SetUpdateCallbackInstance(
105 network_system_clock_context_writer);
106
107 if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) {
108 UNREACHABLE();
109 return;
110 }
111
112 standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
113 sufficient_accuracy);
114 standard_network_system_clock_core.MarkAsInitialized();
115}
116
117void TimeManager::SetupStandardUserSystemClock(
118 Core::System& system, bool is_automatic_correction_enabled,
119 Clock::SteadyClockTimePoint steady_clock_time_point) {
120 if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
121 system, is_automatic_correction_enabled) != RESULT_SUCCESS) {
122 UNREACHABLE();
123 return;
124 }
125
126 standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
127 standard_user_system_clock_core.MarkAsInitialized();
128 shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
129}
130
131void TimeManager::SetupEphemeralNetworkSystemClock() {
132 ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
133 ephemeral_network_system_clock_context_writer);
134 ephemeral_network_system_clock_core.MarkAsInitialized();
135}
136
137} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h
new file mode 100644
index 000000000..8e65f0d22
--- /dev/null
+++ b/src/core/hle/service/time/time_manager.h
@@ -0,0 +1,117 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "core/file_sys/vfs_types.h"
9#include "core/hle/service/time/clock_types.h"
10#include "core/hle/service/time/ephemeral_network_system_clock_core.h"
11#include "core/hle/service/time/standard_local_system_clock_core.h"
12#include "core/hle/service/time/standard_network_system_clock_core.h"
13#include "core/hle/service/time/standard_steady_clock_core.h"
14#include "core/hle/service/time/standard_user_system_clock_core.h"
15#include "core/hle/service/time/tick_based_steady_clock_core.h"
16#include "core/hle/service/time/time_sharedmemory.h"
17#include "core/hle/service/time/time_zone_content_manager.h"
18
19namespace Service::Time {
20
21namespace Clock {
22class EphemeralNetworkSystemClockContextWriter;
23class LocalSystemClockContextWriter;
24class NetworkSystemClockContextWriter;
25} // namespace Clock
26
27// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
28// This code was released under public domain.
29
30class TimeManager final {
31public:
32 explicit TimeManager(Core::System& system);
33 ~TimeManager();
34
35 Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
36 return standard_steady_clock_core;
37 }
38
39 const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
40 return standard_steady_clock_core;
41 }
42
43 Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
44 return standard_local_system_clock_core;
45 }
46
47 const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
48 return standard_local_system_clock_core;
49 }
50
51 Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
52 return standard_network_system_clock_core;
53 }
54
55 const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
56 return standard_network_system_clock_core;
57 }
58
59 Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
60 return standard_user_system_clock_core;
61 }
62
63 const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
64 return standard_user_system_clock_core;
65 }
66
67 TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
68 return time_zone_content_manager;
69 }
70
71 const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
72 return time_zone_content_manager;
73 }
74
75 SharedMemory& GetSharedMemory() {
76 return shared_memory;
77 }
78
79 const SharedMemory& GetSharedMemory() const {
80 return shared_memory;
81 }
82
83 void SetupTimeZoneManager(std::string location_name,
84 Clock::SteadyClockTimePoint time_zone_updated_time_point,
85 std::size_t total_location_name_count, u128 time_zone_rule_version,
86 FileSys::VirtualFile& vfs_file);
87
88private:
89 void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
90 Clock::TimeSpanType setup_value,
91 Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected);
92 void SetupStandardLocalSystemClock(Core::System& system,
93 Clock::SystemClockContext clock_context, s64 posix_time);
94 void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
95 Clock::TimeSpanType sufficient_accuracy);
96 void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
97 Clock::SteadyClockTimePoint steady_clock_time_point);
98 void SetupEphemeralNetworkSystemClock();
99
100 SharedMemory shared_memory;
101
102 Clock::StandardSteadyClockCore standard_steady_clock_core;
103 Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
104 Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
105 Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
106 Clock::StandardUserSystemClockCore standard_user_system_clock_core;
107 Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
108
109 std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
110 std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
111 std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
112 ephemeral_network_system_clock_context_writer;
113
114 TimeZone::TimeZoneContentManager time_zone_content_manager;
115};
116
117} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp
index 4035f5072..9b03191bf 100644
--- a/src/core/hle/service/time/time_sharedmemory.cpp
+++ b/src/core/hle/service/time/time_sharedmemory.cpp
@@ -3,20 +3,21 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/core.h" 5#include "core/core.h"
6#include "core/core_timing.h"
7#include "core/core_timing_util.h"
8#include "core/hle/service/time/clock_types.h"
9#include "core/hle/service/time/steady_clock_core.h"
6#include "core/hle/service/time/time_sharedmemory.h" 10#include "core/hle/service/time/time_sharedmemory.h"
7 11
8namespace Service::Time { 12namespace Service::Time {
9const std::size_t SHARED_MEMORY_SIZE = 0x1000; 13
14static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000};
10 15
11SharedMemory::SharedMemory(Core::System& system) : system(system) { 16SharedMemory::SharedMemory(Core::System& system) : system(system) {
12 shared_memory_holder = Kernel::SharedMemory::Create( 17 shared_memory_holder = Kernel::SharedMemory::Create(
13 system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, 18 system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite,
14 Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory"); 19 Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory");
15 20 std::memset(shared_memory_holder->GetPointer(), 0, SHARED_MEMORY_SIZE);
16 // Seems static from 1.0.0 -> 8.1.0. Specific games seem to check this value and crash
17 // if it's set to anything else
18 shared_memory_format.format_version = 14;
19 std::memcpy(shared_memory_holder->GetPointer(), &shared_memory_format, sizeof(Format));
20} 21}
21 22
22SharedMemory::~SharedMemory() = default; 23SharedMemory::~SharedMemory() = default;
@@ -25,44 +26,32 @@ std::shared_ptr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() cons
25 return shared_memory_holder; 26 return shared_memory_holder;
26} 27}
27 28
28void SharedMemory::SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint) { 29void SharedMemory::SetupStandardSteadyClock(Core::System& system,
30 const Common::UUID& clock_source_id,
31 Clock::TimeSpanType current_time_point) {
32 const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks(
33 Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
34 Core::Timing::CNTFREQ)};
35 const Clock::SteadyClockContext context{
36 static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
37 clock_source_id};
29 shared_memory_format.standard_steady_clock_timepoint.StoreData( 38 shared_memory_format.standard_steady_clock_timepoint.StoreData(
30 shared_memory_holder->GetPointer(), timepoint); 39 shared_memory_holder->GetPointer(), context);
31} 40}
32 41
33void SharedMemory::SetStandardLocalSystemClockContext(const SystemClockContext& context) { 42void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) {
34 shared_memory_format.standard_local_system_clock_context.StoreData( 43 shared_memory_format.standard_local_system_clock_context.StoreData(
35 shared_memory_holder->GetPointer(), context); 44 shared_memory_holder->GetPointer(), context);
36} 45}
37 46
38void SharedMemory::SetStandardNetworkSystemClockContext(const SystemClockContext& context) { 47void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) {
39 shared_memory_format.standard_network_system_clock_context.StoreData( 48 shared_memory_format.standard_network_system_clock_context.StoreData(
40 shared_memory_holder->GetPointer(), context); 49 shared_memory_holder->GetPointer(), context);
41} 50}
42 51
43void SharedMemory::SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled) { 52void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) {
44 shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( 53 shared_memory_format.standard_user_system_clock_automatic_correction.StoreData(
45 shared_memory_holder->GetPointer(), enabled); 54 shared_memory_holder->GetPointer(), is_enabled);
46}
47
48SteadyClockTimePoint SharedMemory::GetStandardSteadyClockTimepoint() {
49 return shared_memory_format.standard_steady_clock_timepoint.ReadData(
50 shared_memory_holder->GetPointer());
51}
52
53SystemClockContext SharedMemory::GetStandardLocalSystemClockContext() {
54 return shared_memory_format.standard_local_system_clock_context.ReadData(
55 shared_memory_holder->GetPointer());
56}
57
58SystemClockContext SharedMemory::GetStandardNetworkSystemClockContext() {
59 return shared_memory_format.standard_network_system_clock_context.ReadData(
60 shared_memory_holder->GetPointer());
61}
62
63bool SharedMemory::GetStandardUserSystemClockAutomaticCorrectionEnabled() {
64 return shared_memory_format.standard_user_system_clock_automatic_correction.ReadData(
65 shared_memory_holder->GetPointer());
66} 55}
67 56
68} // namespace Service::Time 57} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h
index 904a96430..5976b2046 100644
--- a/src/core/hle/service/time/time_sharedmemory.h
+++ b/src/core/hle/service/time/time_sharedmemory.h
@@ -5,11 +5,14 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/uuid.h"
8#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/service/time/time.h" 10#include "core/hle/kernel/thread.h"
11#include "core/hle/service/time/clock_types.h"
10 12
11namespace Service::Time { 13namespace Service::Time {
12class SharedMemory { 14
15class SharedMemory final {
13public: 16public:
14 explicit SharedMemory(Core::System& system); 17 explicit SharedMemory(Core::System& system);
15 ~SharedMemory(); 18 ~SharedMemory();
@@ -17,22 +20,10 @@ public:
17 // Return the shared memory handle 20 // Return the shared memory handle
18 std::shared_ptr<Kernel::SharedMemory> GetSharedMemoryHolder() const; 21 std::shared_ptr<Kernel::SharedMemory> GetSharedMemoryHolder() const;
19 22
20 // Set memory barriers in shared memory and update them
21 void SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint);
22 void SetStandardLocalSystemClockContext(const SystemClockContext& context);
23 void SetStandardNetworkSystemClockContext(const SystemClockContext& context);
24 void SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled);
25
26 // Pull from memory barriers in the shared memory
27 SteadyClockTimePoint GetStandardSteadyClockTimepoint();
28 SystemClockContext GetStandardLocalSystemClockContext();
29 SystemClockContext GetStandardNetworkSystemClockContext();
30 bool GetStandardUserSystemClockAutomaticCorrectionEnabled();
31
32 // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? 23 // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this?
33 template <typename T, std::size_t Offset> 24 template <typename T, std::size_t Offset>
34 struct MemoryBarrier { 25 struct MemoryBarrier {
35 static_assert(std::is_trivially_constructible_v<T>, "T must be trivially constructable"); 26 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
36 u32_le read_attempt{}; 27 u32_le read_attempt{};
37 std::array<T, 2> data{}; 28 std::array<T, 2> data{};
38 29
@@ -57,16 +48,22 @@ public:
57 48
58 // Shared memory format 49 // Shared memory format
59 struct Format { 50 struct Format {
60 MemoryBarrier<SteadyClockTimePoint, 0x0> standard_steady_clock_timepoint; 51 MemoryBarrier<Clock::SteadyClockContext, 0x0> standard_steady_clock_timepoint;
61 MemoryBarrier<SystemClockContext, 0x38> standard_local_system_clock_context; 52 MemoryBarrier<Clock::SystemClockContext, 0x38> standard_local_system_clock_context;
62 MemoryBarrier<SystemClockContext, 0x80> standard_network_system_clock_context; 53 MemoryBarrier<Clock::SystemClockContext, 0x80> standard_network_system_clock_context;
63 MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction; 54 MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction;
64 u32_le format_version; 55 u32_le format_version;
65 }; 56 };
66 static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); 57 static_assert(sizeof(Format) == 0xd8, "Format is an invalid size");
67 58
59 void SetupStandardSteadyClock(Core::System& system, const Common::UUID& clock_source_id,
60 Clock::TimeSpanType currentTimePoint);
61 void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context);
62 void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context);
63 void SetAutomaticCorrectionEnabled(bool is_enabled);
64
68private: 65private:
69 std::shared_ptr<Kernel::SharedMemory> shared_memory_holder{}; 66 std::shared_ptr<Kernel::SharedMemory> shared_memory_holder;
70 Core::System& system; 67 Core::System& system;
71 Format shared_memory_format{}; 68 Format shared_memory_format{};
72}; 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
new file mode 100644
index 000000000..57b1a2bca
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -0,0 +1,125 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <sstream>
6
7#include "common/logging/log.h"
8#include "core/core.h"
9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/nca_metadata.h"
11#include "core/file_sys/registered_cache.h"
12#include "core/file_sys/romfs.h"
13#include "core/file_sys/system_archive/system_archive.h"
14#include "core/hle/service/filesystem/filesystem.h"
15#include "core/hle/service/time/time_manager.h"
16#include "core/hle/service/time/time_zone_content_manager.h"
17
18namespace Service::Time::TimeZone {
19
20constexpr u64 time_zone_binary_titleid{0x010000000000080E};
21
22static FileSys::VirtualDir GetTimeZoneBinary(Core::System& system) {
23 const auto* nand{system.GetFileSystemController().GetSystemNANDContents()};
24 const auto nca{nand->GetEntry(time_zone_binary_titleid, FileSys::ContentRecordType::Data)};
25
26 FileSys::VirtualFile romfs;
27 if (nca) {
28 romfs = nca->GetRomFS();
29 }
30
31 if (!romfs) {
32 romfs = FileSys::SystemArchive::SynthesizeSystemArchive(time_zone_binary_titleid);
33 }
34
35 if (!romfs) {
36 LOG_ERROR(Service_Time, "Failed to find or synthesize {:016X!}", time_zone_binary_titleid);
37 return {};
38 }
39
40 return FileSys::ExtractRomFS(romfs);
41}
42
43static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
44 const FileSys::VirtualDir extracted_romfs{GetTimeZoneBinary(system)};
45 if (!extracted_romfs) {
46 LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
47 return {};
48 }
49
50 const FileSys::VirtualFile binary_list{extracted_romfs->GetFile("binaryList.txt")};
51 if (!binary_list) {
52 LOG_ERROR(Service_Time, "{:016X} has no file binaryList.txt!", time_zone_binary_titleid);
53 return {};
54 }
55
56 std::vector<char> raw_data(binary_list->GetSize());
57 binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
58
59 std::stringstream data_stream{raw_data.data()};
60 std::string name;
61 std::vector<std::string> location_name_cache;
62 while (std::getline(data_stream, name)) {
63 name.pop_back(); // Remove carriage return
64 location_name_cache.emplace_back(std::move(name));
65 }
66 return location_name_cache;
67}
68
69TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system)
70 : system{system}, location_name_cache{BuildLocationNameCache(system)} {
71 if (FileSys::VirtualFile vfs_file; GetTimeZoneInfoFile("GMT", vfs_file) == RESULT_SUCCESS) {
72 const auto time_point{
73 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
74 time_manager.SetupTimeZoneManager("GMT", time_point, location_name_cache.size(), {},
75 vfs_file);
76 } else {
77 time_zone_manager.MarkAsInitialized();
78 }
79}
80
81ResultCode TimeZoneContentManager::LoadTimeZoneRule(TimeZoneRule& rules,
82 const std::string& location_name) const {
83 FileSys::VirtualFile vfs_file;
84 if (const ResultCode result{GetTimeZoneInfoFile(location_name, vfs_file)};
85 result != RESULT_SUCCESS) {
86 return result;
87 }
88
89 return time_zone_manager.ParseTimeZoneRuleBinary(rules, vfs_file);
90}
91
92bool TimeZoneContentManager::IsLocationNameValid(const std::string& location_name) const {
93 return std::find(location_name_cache.begin(), location_name_cache.end(), location_name) !=
94 location_name_cache.end();
95}
96
97ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_name,
98 FileSys::VirtualFile& vfs_file) const {
99 if (!IsLocationNameValid(location_name)) {
100 return ERROR_TIME_NOT_FOUND;
101 }
102
103 const FileSys::VirtualDir extracted_romfs{GetTimeZoneBinary(system)};
104 if (!extracted_romfs) {
105 LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
106 return ERROR_TIME_NOT_FOUND;
107 }
108
109 const FileSys::VirtualDir zoneinfo_dir{extracted_romfs->GetSubdirectory("zoneinfo")};
110 if (!zoneinfo_dir) {
111 LOG_ERROR(Service_Time, "{:016X} has no directory zoneinfo!", time_zone_binary_titleid);
112 return ERROR_TIME_NOT_FOUND;
113 }
114
115 vfs_file = zoneinfo_dir->GetFile(location_name);
116 if (!vfs_file) {
117 LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"!", time_zone_binary_titleid,
118 location_name);
119 return ERROR_TIME_NOT_FOUND;
120 }
121
122 return RESULT_SUCCESS;
123}
124
125} // namespace Service::Time::TimeZone
diff --git a/src/core/hle/service/time/time_zone_content_manager.h b/src/core/hle/service/time/time_zone_content_manager.h
new file mode 100644
index 000000000..4f302c3b9
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_content_manager.h
@@ -0,0 +1,46 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8#include <vector>
9
10#include "core/hle/service/time/time_zone_manager.h"
11
12namespace Core {
13class System;
14}
15
16namespace Service::Time {
17class TimeManager;
18}
19
20namespace Service::Time::TimeZone {
21
22class TimeZoneContentManager final {
23public:
24 TimeZoneContentManager(TimeManager& time_manager, Core::System& system);
25
26 TimeZoneManager& GetTimeZoneManager() {
27 return time_zone_manager;
28 }
29
30 const TimeZoneManager& GetTimeZoneManager() const {
31 return time_zone_manager;
32 }
33
34 ResultCode LoadTimeZoneRule(TimeZoneRule& rules, const std::string& location_name) const;
35
36private:
37 bool IsLocationNameValid(const std::string& location_name) const;
38 ResultCode GetTimeZoneInfoFile(const std::string& location_name,
39 FileSys::VirtualFile& vfs_file) const;
40
41 Core::System& system;
42 TimeZoneManager time_zone_manager;
43 const std::vector<std::string> location_name_cache;
44};
45
46} // namespace Service::Time::TimeZone
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
new file mode 100644
index 000000000..717e81818
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -0,0 +1,1030 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <climits>
6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/nca_metadata.h"
11#include "core/file_sys/registered_cache.h"
12#include "core/file_sys/romfs.h"
13#include "core/file_sys/system_archive/system_archive.h"
14#include "core/hle/service/time/time_zone_manager.h"
15
16namespace Service::Time::TimeZone {
17
18static constexpr s32 epoch_year{1970};
19static constexpr s32 year_base{1900};
20static constexpr s32 epoch_week_day{4};
21static constexpr s32 seconds_per_minute{60};
22static constexpr s32 minutes_per_hour{60};
23static constexpr s32 hours_per_day{24};
24static constexpr s32 days_per_week{7};
25static constexpr s32 days_per_normal_year{365};
26static constexpr s32 days_per_leap_year{366};
27static constexpr s32 months_per_year{12};
28static constexpr s32 seconds_per_hour{seconds_per_minute * minutes_per_hour};
29static constexpr s32 seconds_per_day{seconds_per_hour * hours_per_day};
30static constexpr s32 years_per_repeat{400};
31static constexpr s64 average_seconds_per_year{31556952};
32static constexpr s64 seconds_per_repeat{years_per_repeat * average_seconds_per_year};
33
34struct Rule {
35 enum class Type : u32 { JulianDay, DayOfYear, MonthNthDayOfWeek };
36 Type rule_type{};
37 s32 day{};
38 s32 week{};
39 s32 month{};
40 s32 transition_time{};
41};
42
43struct CalendarTimeInternal {
44 s64 year{};
45 s8 month{};
46 s8 day{};
47 s8 hour{};
48 s8 minute{};
49 s8 second{};
50 int Compare(const CalendarTimeInternal& other) const {
51 if (year != other.year) {
52 if (year < other.year) {
53 return -1;
54 }
55 return 1;
56 }
57 if (month != other.month) {
58 return month - other.month;
59 }
60 if (day != other.day) {
61 return day - other.day;
62 }
63 if (hour != other.hour) {
64 return hour - other.hour;
65 }
66 if (minute != other.minute) {
67 return minute - other.minute;
68 }
69 if (second != other.second) {
70 return second - other.second;
71 }
72 return {};
73 }
74};
75
76template <typename TResult, typename TOperand>
77static bool SafeAdd(TResult& result, TOperand op) {
78 result = result + op;
79 return true;
80}
81
82template <typename TResult, typename TUnit, typename TBase>
83static bool SafeNormalize(TResult& result, TUnit& unit, TBase base) {
84 TUnit delta{};
85 if (unit >= 0) {
86 delta = unit / base;
87 } else {
88 delta = -1 - (-1 - unit) / base;
89 }
90 unit -= delta * base;
91 return SafeAdd(result, delta);
92}
93
94template <typename T>
95static constexpr bool IsLeapYear(T year) {
96 return ((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0);
97}
98
99template <typename T>
100static constexpr T GetYearLengthInDays(T year) {
101 return IsLeapYear(year) ? days_per_leap_year : days_per_normal_year;
102}
103
104static constexpr s64 GetLeapDaysFromYearPositive(s64 year) {
105 return year / 4 - year / 100 + year / years_per_repeat;
106}
107
108static constexpr s64 GetLeapDaysFromYear(s64 year) {
109 if (year < 0) {
110 return -1 - GetLeapDaysFromYearPositive(-1 - year);
111 } else {
112 return GetLeapDaysFromYearPositive(year);
113 }
114}
115
116static constexpr int GetMonthLength(bool is_leap_year, int month) {
117 constexpr std::array<int, 12> month_lengths{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
118 constexpr std::array<int, 12> month_lengths_leap{31, 29, 31, 30, 31, 30,
119 31, 31, 30, 31, 30, 31};
120 return is_leap_year ? month_lengths_leap[month] : month_lengths[month];
121}
122
123static constexpr bool IsDigit(char value) {
124 return value >= '0' && value <= '9';
125}
126
127static constexpr int GetQZName(const char* name, int offset, char delimiter) {
128 while (name[offset] != '\0' && name[offset] != delimiter) {
129 offset++;
130 }
131 return offset;
132}
133
134static constexpr int GetTZName(const char* name, int offset) {
135 for (char value{name[offset]};
136 value != '\0' && !IsDigit(value) && value != ',' && value != '-' && value != '+';
137 offset++) {
138 value = name[offset];
139 }
140 return offset;
141}
142
143static constexpr bool GetInteger(const char* name, int& offset, int& value, int min, int max) {
144 value = 0;
145 char temp{name[offset]};
146 if (!IsDigit(temp)) {
147 return {};
148 }
149 do {
150 value = value * 10 + (temp - '0');
151 if (value > max) {
152 return {};
153 }
154 temp = name[offset];
155 } while (IsDigit(temp));
156
157 return value >= min;
158}
159
160static constexpr bool GetSeconds(const char* name, int& offset, int& seconds) {
161 seconds = 0;
162 int value{};
163 if (!GetInteger(name, offset, value, 0, hours_per_day * days_per_week - 1)) {
164 return {};
165 }
166 seconds = value * seconds_per_hour;
167
168 if (name[offset] == ':') {
169 offset++;
170 if (!GetInteger(name, offset, value, 0, minutes_per_hour - 1)) {
171 return {};
172 }
173 seconds += value * seconds_per_minute;
174 if (name[offset] == ':') {
175 offset++;
176 if (!GetInteger(name, offset, value, 0, seconds_per_minute)) {
177 return {};
178 }
179 seconds += value;
180 }
181 }
182 return true;
183}
184
185static constexpr bool GetOffset(const char* name, int& offset, int& value) {
186 bool is_negative{};
187 if (name[offset] == '-') {
188 is_negative = true;
189 offset++;
190 } else if (name[offset] == '+') {
191 offset++;
192 }
193 if (!GetSeconds(name, offset, value)) {
194 return {};
195 }
196 if (is_negative) {
197 value = -value;
198 }
199 return true;
200}
201
202static constexpr bool GetRule(const char* name, int& position, Rule& rule) {
203 bool is_valid{};
204 if (name[position] == 'J') {
205 position++;
206 rule.rule_type = Rule::Type::JulianDay;
207 is_valid = GetInteger(name, position, rule.day, 1, days_per_normal_year);
208 } else if (name[position] == 'M') {
209 position++;
210 rule.rule_type = Rule::Type::MonthNthDayOfWeek;
211 is_valid = GetInteger(name, position, rule.month, 1, months_per_year);
212 if (!is_valid) {
213 return {};
214 }
215 if (name[position++] != '.') {
216 return {};
217 }
218 is_valid = GetInteger(name, position, rule.week, 1, 5);
219 if (!is_valid) {
220 return {};
221 }
222 if (name[position++] != '.') {
223 return {};
224 }
225 is_valid = GetInteger(name, position, rule.day, 0, days_per_week - 1);
226 } else if (isdigit(name[position])) {
227 rule.rule_type = Rule::Type::DayOfYear;
228 is_valid = GetInteger(name, position, rule.day, 0, days_per_leap_year - 1);
229 } else {
230 return {};
231 }
232 if (!is_valid) {
233 return {};
234 }
235 if (name[position] == '/') {
236 position++;
237 return GetOffset(name, position, rule.transition_time);
238 } else {
239 rule.transition_time = 2 * seconds_per_hour;
240 }
241 return true;
242}
243
244static constexpr int TransitionTime(int year, Rule rule, int offset) {
245 int value{};
246 switch (rule.rule_type) {
247 case Rule::Type::JulianDay:
248 value = (rule.day - 1) * seconds_per_day;
249 if (IsLeapYear(year) && rule.day >= 60) {
250 value += seconds_per_day;
251 }
252 break;
253 case Rule::Type::DayOfYear:
254 value = rule.day * seconds_per_day;
255 break;
256 case Rule::Type::MonthNthDayOfWeek: {
257 // Use Zeller's Congruence (https://en.wikipedia.org/wiki/Zeller%27s_congruence) to
258 // calculate the day of the week for any Julian or Gregorian calendar date.
259 const int m1{(rule.month + 9) % 12 + 1};
260 const int yy0{(rule.month <= 2) ? (year - 1) : year};
261 const int yy1{yy0 / 100};
262 const int yy2{yy0 % 100};
263 int day_of_week{((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7};
264
265 if (day_of_week < 0) {
266 day_of_week += days_per_week;
267 }
268 int day{rule.day - day_of_week};
269 if (day < 0) {
270 day += days_per_week;
271 }
272 for (int i{1}; i < rule.week; i++) {
273 if (day + days_per_week >= GetMonthLength(IsLeapYear(year), rule.month - 1)) {
274 break;
275 }
276 day += days_per_week;
277 }
278
279 value = day * seconds_per_day;
280 for (int index{}; index < rule.month - 1; ++index) {
281 value += GetMonthLength(IsLeapYear(year), index) * seconds_per_day;
282 }
283 break;
284 }
285 default:
286 UNREACHABLE();
287 }
288 return value + rule.transition_time + offset;
289}
290
291static bool ParsePosixName(const char* name, TimeZoneRule& rule) {
292 constexpr char default_rule[]{",M4.1.0,M10.5.0"};
293 const char* std_name{name};
294 int std_len{};
295 int offset{};
296 int std_offset{};
297
298 if (name[offset] == '<') {
299 offset++;
300 std_name = name + offset;
301 const int std_name_offset{offset};
302 offset = GetQZName(name, offset, '>');
303 if (name[offset] != '>') {
304 return {};
305 }
306 std_len = offset - std_name_offset;
307 offset++;
308 } else {
309 offset = GetTZName(name, offset);
310 std_len = offset;
311 }
312 if (!std_len) {
313 return {};
314 }
315 if (!GetOffset(name, offset, std_offset)) {
316 return {};
317 }
318
319 int char_count{std_len + 1};
320 int dest_len{};
321 int dest_offset{};
322 const char* dest_name{name + offset};
323 if (rule.chars.size() < char_count) {
324 return {};
325 }
326
327 if (name[offset] != '\0') {
328 if (name[offset] == '<') {
329 dest_name = name + (++offset);
330 const int dest_name_offset{offset};
331 offset = GetQZName(name, offset, '>');
332 if (name[offset] != '>') {
333 return {};
334 }
335 dest_len = offset - dest_name_offset;
336 offset++;
337 } else {
338 dest_name = name + (offset);
339 offset = GetTZName(name, offset);
340 dest_len = offset;
341 }
342 if (dest_len == 0) {
343 return {};
344 }
345 char_count += dest_len + 1;
346 if (rule.chars.size() < char_count) {
347 return {};
348 }
349 if (name[offset] != '\0' && name[offset] != ',' && name[offset] != ';') {
350 if (!GetOffset(name, offset, dest_offset)) {
351 return {};
352 }
353 } else {
354 dest_offset = std_offset - seconds_per_hour;
355 }
356 if (name[offset] == '\0') {
357 name = default_rule;
358 offset = 0;
359 }
360 if (name[offset] == ',' || name[offset] == ';') {
361 offset++;
362
363 Rule start{};
364 if (!GetRule(name, offset, start)) {
365 return {};
366 }
367 if (name[offset++] != ',') {
368 return {};
369 }
370
371 Rule end{};
372 if (!GetRule(name, offset, end)) {
373 return {};
374 }
375 if (name[offset] != '\0') {
376 return {};
377 }
378
379 rule.type_count = 2;
380 rule.ttis[0].gmt_offset = -dest_offset;
381 rule.ttis[0].is_dst = true;
382 rule.ttis[0].abbreviation_list_index = std_len + 1;
383 rule.ttis[1].gmt_offset = -std_offset;
384 rule.ttis[1].is_dst = false;
385 rule.ttis[1].abbreviation_list_index = 0;
386 rule.default_type = 0;
387
388 s64 jan_first{};
389 int time_count{};
390 int jan_offset{};
391 int year_beginning{epoch_year};
392 do {
393 const int year_seconds{GetYearLengthInDays(year_beginning - 1) * seconds_per_day};
394 year_beginning--;
395 if (!SafeAdd(jan_first, -year_seconds)) {
396 jan_offset = -year_seconds;
397 break;
398 }
399 } while (epoch_year - years_per_repeat / 2 < year_beginning);
400
401 int year_limit{year_beginning + years_per_repeat + 1};
402 int year{};
403 for (year = year_beginning; year < year_limit; year++) {
404 int start_time{TransitionTime(year, start, std_offset)};
405 int end_time{TransitionTime(year, end, dest_offset)};
406 const int year_seconds{GetYearLengthInDays(year) * seconds_per_day};
407 const bool is_reversed{end_time < start_time};
408 if (is_reversed) {
409 int swap{start_time};
410 start_time = end_time;
411 end_time = swap;
412 }
413
414 if (is_reversed ||
415 (start_time < end_time &&
416 (end_time - start_time < (year_seconds + (std_offset - dest_offset))))) {
417 if (rule.ats.size() - 2 < time_count) {
418 break;
419 }
420
421 rule.ats[time_count] = jan_first;
422 if (SafeAdd(rule.ats[time_count], jan_offset + start_time)) {
423 rule.types[time_count++] = is_reversed ? 1 : 0;
424 } else if (jan_offset != 0) {
425 rule.default_type = is_reversed ? 1 : 0;
426 }
427
428 rule.ats[time_count] = jan_first;
429 if (SafeAdd(rule.ats[time_count], jan_offset + end_time)) {
430 rule.types[time_count++] = is_reversed ? 0 : 1;
431 year_limit = year + years_per_repeat + 1;
432 } else if (jan_offset != 0) {
433 rule.default_type = is_reversed ? 0 : 1;
434 }
435 }
436 if (!SafeAdd(jan_first, jan_offset + year_seconds)) {
437 break;
438 }
439 jan_offset = 0;
440 }
441 rule.time_count = time_count;
442 if (time_count == 0) {
443 rule.type_count = 1;
444 } else if (years_per_repeat < year - year_beginning) {
445 rule.go_back = true;
446 rule.go_ahead = true;
447 }
448 } else {
449 if (name[offset] == '\0') {
450 return {};
451 }
452
453 s64 their_std_offset{};
454 for (int index{}; index < rule.time_count; ++index) {
455 const s8 type{rule.types[index]};
456 if (rule.ttis[type].is_standard_time_daylight) {
457 their_std_offset = -rule.ttis[type].gmt_offset;
458 }
459 }
460
461 s64 their_offset{their_std_offset};
462 for (int index{}; index < rule.time_count; ++index) {
463 const s8 type{rule.types[index]};
464 rule.types[index] = rule.ttis[type].is_dst ? 1 : 0;
465 if (!rule.ttis[type].is_gmt) {
466 if (!rule.ttis[type].is_standard_time_daylight) {
467 rule.ats[index] += dest_offset - their_std_offset;
468 } else {
469 rule.ats[index] += std_offset - their_std_offset;
470 }
471 }
472 their_offset = -rule.ttis[type].gmt_offset;
473 if (!rule.ttis[type].is_dst) {
474 their_std_offset = their_offset;
475 }
476 }
477 rule.ttis[0].gmt_offset = -std_offset;
478 rule.ttis[0].is_dst = false;
479 rule.ttis[0].abbreviation_list_index = 0;
480 rule.ttis[1].gmt_offset = -dest_offset;
481 rule.ttis[1].is_dst = true;
482 rule.ttis[1].abbreviation_list_index = std_len + 1;
483 rule.type_count = 2;
484 rule.default_type = 0;
485 }
486 } else {
487 // Default is standard time
488 rule.type_count = 1;
489 rule.time_count = 0;
490 rule.default_type = 0;
491 rule.ttis[0].gmt_offset = -std_offset;
492 rule.ttis[0].is_dst = false;
493 rule.ttis[0].abbreviation_list_index = 0;
494 }
495
496 rule.char_count = char_count;
497 for (int index{}; index < std_len; ++index) {
498 rule.chars[index] = std_name[index];
499 }
500
501 rule.chars[std_len++] = '\0';
502 if (dest_len != 0) {
503 for (int index{}; index < dest_len; ++index) {
504 rule.chars[std_len + index] = dest_name[index];
505 }
506 rule.chars[std_len + dest_len] = '\0';
507 }
508
509 return true;
510}
511
512static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFile& vfs_file) {
513 TzifHeader header{};
514 if (vfs_file->ReadObject<TzifHeader>(&header) != sizeof(TzifHeader)) {
515 return {};
516 }
517
518 constexpr s32 time_zone_max_leaps{50};
519 constexpr s32 time_zone_max_chars{50};
520 if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps &&
521 0 < header.type_count && header.type_count < time_zone_rule.ttis.size() &&
522 0 <= header.time_count && header.time_count < time_zone_rule.ats.size() &&
523 0 <= header.char_count && header.char_count < time_zone_max_chars &&
524 (header.ttis_std_count == header.type_count || header.ttis_std_count == 0) &&
525 (header.ttis_gmt_count == header.type_count || header.ttis_gmt_count == 0))) {
526 return {};
527 }
528 time_zone_rule.time_count = header.time_count;
529 time_zone_rule.type_count = header.type_count;
530 time_zone_rule.char_count = header.char_count;
531
532 int time_count{};
533 u64 read_offset = sizeof(TzifHeader);
534 for (int index{}; index < time_zone_rule.time_count; ++index) {
535 s64_be at{};
536 vfs_file->ReadObject<s64_be>(&at, read_offset);
537 time_zone_rule.types[index] = 1;
538 if (time_count != 0 && at <= time_zone_rule.ats[time_count - 1]) {
539 if (at < time_zone_rule.ats[time_count - 1]) {
540 return {};
541 }
542 time_zone_rule.types[index - 1] = 0;
543 time_count--;
544 }
545 time_zone_rule.ats[time_count++] = at;
546 read_offset += sizeof(s64_be);
547 }
548 time_count = 0;
549 for (int index{}; index < time_zone_rule.time_count; ++index) {
550 const u8 type{*vfs_file->ReadByte(read_offset)};
551 read_offset += sizeof(u8);
552 if (time_zone_rule.time_count <= type) {
553 return {};
554 }
555 if (time_zone_rule.types[index] != 0) {
556 time_zone_rule.types[time_count++] = type;
557 }
558 }
559 time_zone_rule.time_count = time_count;
560 for (int index{}; index < time_zone_rule.type_count; ++index) {
561 TimeTypeInfo& ttis{time_zone_rule.ttis[index]};
562 u32_be gmt_offset{};
563 vfs_file->ReadObject<u32_be>(&gmt_offset, read_offset);
564 read_offset += sizeof(u32_be);
565 ttis.gmt_offset = gmt_offset;
566
567 const u8 dst{*vfs_file->ReadByte(read_offset)};
568 read_offset += sizeof(u8);
569 if (dst >= 2) {
570 return {};
571 }
572 ttis.is_dst = dst != 0;
573
574 const s32 abbreviation_list_index{*vfs_file->ReadByte(read_offset)};
575 read_offset += sizeof(u8);
576 if (abbreviation_list_index >= time_zone_rule.char_count) {
577 return {};
578 }
579 ttis.abbreviation_list_index = abbreviation_list_index;
580 }
581
582 vfs_file->ReadArray(time_zone_rule.chars.data(), time_zone_rule.char_count, read_offset);
583 time_zone_rule.chars[time_zone_rule.char_count] = '\0';
584 read_offset += time_zone_rule.char_count;
585 for (int index{}; index < time_zone_rule.type_count; ++index) {
586 if (header.ttis_std_count == 0) {
587 time_zone_rule.ttis[index].is_standard_time_daylight = false;
588 } else {
589 const u8 dst{*vfs_file->ReadByte(read_offset)};
590 read_offset += sizeof(u8);
591 if (dst >= 2) {
592 return {};
593 }
594 time_zone_rule.ttis[index].is_standard_time_daylight = dst != 0;
595 }
596 }
597
598 for (int index{}; index < time_zone_rule.type_count; ++index) {
599 if (header.ttis_std_count == 0) {
600 time_zone_rule.ttis[index].is_gmt = false;
601 } else {
602 const u8 dst{*vfs_file->ReadByte(read_offset)};
603 read_offset += sizeof(u8);
604 if (dst >= 2) {
605 return {};
606 }
607 time_zone_rule.ttis[index].is_gmt = dst != 0;
608 }
609 }
610
611 const u64 position{(read_offset - sizeof(TzifHeader))};
612 const std::size_t bytes_read{vfs_file->GetSize() - sizeof(TzifHeader) - position};
613 if (bytes_read < 0) {
614 return {};
615 }
616 constexpr s32 time_zone_name_max{255};
617 if (bytes_read > (time_zone_name_max + 1)) {
618 return {};
619 }
620
621 std::array<char, time_zone_name_max + 1> temp_name{};
622 vfs_file->ReadArray(temp_name.data(), bytes_read, read_offset);
623 if (bytes_read > 2 && temp_name[0] == '\n' && temp_name[bytes_read - 1] == '\n' &&
624 time_zone_rule.type_count + 2 <= time_zone_rule.ttis.size()) {
625 temp_name[bytes_read - 1] = '\0';
626
627 std::array<char, time_zone_name_max> name{};
628 std::memcpy(name.data(), temp_name.data() + 1, bytes_read - 1);
629
630 TimeZoneRule temp_rule;
631 if (ParsePosixName(name.data(), temp_rule)) {
632 UNIMPLEMENTED();
633 }
634 }
635 if (time_zone_rule.type_count == 0) {
636 return {};
637 }
638 if (time_zone_rule.time_count > 1) {
639 UNIMPLEMENTED();
640 }
641
642 s32 default_type{};
643
644 for (default_type = 0; default_type < time_zone_rule.time_count; default_type++) {
645 if (time_zone_rule.types[default_type] == 0) {
646 break;
647 }
648 }
649
650 default_type = default_type < time_zone_rule.time_count ? -1 : 0;
651 if (default_type < 0 && time_zone_rule.time_count > 0 &&
652 time_zone_rule.ttis[time_zone_rule.types[0]].is_dst) {
653 default_type = time_zone_rule.types[0];
654 while (--default_type >= 0) {
655 if (!time_zone_rule.ttis[default_type].is_dst) {
656 break;
657 }
658 }
659 }
660 if (default_type < 0) {
661 default_type = 0;
662 while (time_zone_rule.ttis[default_type].is_dst) {
663 if (++default_type >= time_zone_rule.type_count) {
664 default_type = 0;
665 break;
666 }
667 }
668 }
669 time_zone_rule.default_type = default_type;
670 return true;
671}
672
673static ResultCode CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInternal& calendar_time,
674 CalendarAdditionalInfo& calendar_additional_info) {
675 s64 year{epoch_year};
676 s64 time_days{time / seconds_per_day};
677 s64 remaining_seconds{time % seconds_per_day};
678 while (time_days < 0 || time_days >= GetYearLengthInDays(year)) {
679 s64 delta = time_days / days_per_leap_year;
680 if (!delta) {
681 delta = time_days < 0 ? -1 : 1;
682 }
683 s64 new_year{year};
684 if (!SafeAdd(new_year, delta)) {
685 return ERROR_OUT_OF_RANGE;
686 }
687 time_days -= (new_year - year) * days_per_normal_year;
688 time_days -= GetLeapDaysFromYear(new_year - 1) - GetLeapDaysFromYear(year - 1);
689 year = new_year;
690 }
691
692 s64 day_of_year{time_days};
693 remaining_seconds += gmt_offset;
694 while (remaining_seconds < 0) {
695 remaining_seconds += seconds_per_day;
696 day_of_year--;
697 }
698
699 while (remaining_seconds >= seconds_per_day) {
700 remaining_seconds -= seconds_per_day;
701 day_of_year++;
702 }
703
704 while (day_of_year < 0) {
705 if (!SafeAdd(year, -1)) {
706 return ERROR_OUT_OF_RANGE;
707 }
708 day_of_year += GetYearLengthInDays(year);
709 }
710
711 while (day_of_year >= GetYearLengthInDays(year)) {
712 day_of_year -= GetYearLengthInDays(year);
713 if (!SafeAdd(year, 1)) {
714 return ERROR_OUT_OF_RANGE;
715 }
716 }
717
718 calendar_time.year = year;
719 calendar_additional_info.day_of_year = static_cast<u32>(day_of_year);
720 s64 day_of_week{
721 (epoch_week_day +
722 ((year - epoch_year) % days_per_week) * (days_per_normal_year % days_per_week) +
723 GetLeapDaysFromYear(year - 1) - GetLeapDaysFromYear(epoch_year - 1) + day_of_year) %
724 days_per_week};
725 if (day_of_week < 0) {
726 day_of_week += days_per_week;
727 }
728
729 calendar_additional_info.day_of_week = static_cast<u32>(day_of_week);
730 calendar_time.hour = static_cast<s8>((remaining_seconds / seconds_per_hour) % seconds_per_hour);
731 remaining_seconds %= seconds_per_hour;
732 calendar_time.minute = static_cast<s8>(remaining_seconds / seconds_per_minute);
733 calendar_time.second = static_cast<s8>(remaining_seconds % seconds_per_minute);
734
735 for (calendar_time.month = 0;
736 day_of_year >= GetMonthLength(IsLeapYear(year), calendar_time.month);
737 ++calendar_time.month) {
738 day_of_year -= GetMonthLength(IsLeapYear(year), calendar_time.month);
739 }
740
741 calendar_time.day = static_cast<s8>(day_of_year + 1);
742 calendar_additional_info.is_dst = false;
743 calendar_additional_info.gmt_offset = gmt_offset;
744
745 return RESULT_SUCCESS;
746}
747
748static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
749 CalendarTimeInternal& calendar_time,
750 CalendarAdditionalInfo& calendar_additional_info) {
751 if ((rules.go_ahead && time < rules.ats[0]) ||
752 (rules.go_back && time > rules.ats[rules.time_count - 1])) {
753 s64 seconds{};
754 if (time < rules.ats[0]) {
755 seconds = rules.ats[0] - time;
756 } else {
757 seconds = time - rules.ats[rules.time_count - 1];
758 }
759 seconds--;
760
761 const s64 years{(seconds / seconds_per_repeat + 1) * years_per_repeat};
762 seconds = years * average_seconds_per_year;
763
764 s64 new_time{time};
765 if (time < rules.ats[0]) {
766 new_time += seconds;
767 } else {
768 new_time -= seconds;
769 }
770 if (new_time < rules.ats[0] && new_time > rules.ats[rules.time_count - 1]) {
771 return ERROR_TIME_NOT_FOUND;
772 }
773 if (const ResultCode result{
774 ToCalendarTimeInternal(rules, new_time, calendar_time, calendar_additional_info)};
775 result != RESULT_SUCCESS) {
776 return result;
777 }
778 if (time < rules.ats[0]) {
779 calendar_time.year -= years;
780 } else {
781 calendar_time.year += years;
782 }
783
784 return RESULT_SUCCESS;
785 }
786
787 s32 tti_index{};
788 if (rules.time_count == 0 || time < rules.ats[0]) {
789 tti_index = rules.default_type;
790 } else {
791 s32 low{1};
792 s32 high{rules.time_count};
793 while (low < high) {
794 s32 mid{(low + high) >> 1};
795 if (time < rules.ats[mid]) {
796 high = mid;
797 } else {
798 low = mid + 1;
799 }
800 }
801 tti_index = rules.types[low - 1];
802 }
803
804 if (const ResultCode result{CreateCalendarTime(time, rules.ttis[tti_index].gmt_offset,
805 calendar_time, calendar_additional_info)};
806 result != RESULT_SUCCESS) {
807 return result;
808 }
809
810 calendar_additional_info.is_dst = rules.ttis[tti_index].is_dst;
811 const char* time_zone{&rules.chars[rules.ttis[tti_index].abbreviation_list_index]};
812 for (int index{}; time_zone[index] != '\0'; ++index) {
813 calendar_additional_info.timezone_name[index] = time_zone[index];
814 }
815 return RESULT_SUCCESS;
816}
817
818static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) {
819 CalendarTimeInternal calendar_time{};
820 const ResultCode result{
821 ToCalendarTimeInternal(rules, time, calendar_time, calendar.additiona_info)};
822 calendar.time.year = static_cast<s16>(calendar_time.year);
823 calendar.time.month = calendar_time.month + 1; // Internal impl. uses 0-indexed month
824 calendar.time.day = calendar_time.day;
825 calendar.time.hour = calendar_time.hour;
826 calendar.time.minute = calendar_time.minute;
827 calendar.time.second = calendar_time.second;
828 return result;
829}
830
831TimeZoneManager::TimeZoneManager() = default;
832TimeZoneManager::~TimeZoneManager() = default;
833
834ResultCode TimeZoneManager::ToCalendarTime(const TimeZoneRule& rules, s64 time,
835 CalendarInfo& calendar) const {
836 return ToCalendarTimeImpl(rules, time, calendar);
837}
838
839ResultCode TimeZoneManager::SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
840 FileSys::VirtualFile& vfs_file) {
841 TimeZoneRule rule{};
842 if (ParseTimeZoneBinary(rule, vfs_file)) {
843 device_location_name = location_name;
844 time_zone_rule = rule;
845 return RESULT_SUCCESS;
846 }
847 return ERROR_TIME_ZONE_CONVERSION_FAILED;
848}
849
850ResultCode TimeZoneManager::SetUpdatedTime(const Clock::SteadyClockTimePoint& value) {
851 time_zone_update_time_point = value;
852 return RESULT_SUCCESS;
853}
854
855ResultCode TimeZoneManager::ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const {
856 if (is_initialized) {
857 return ToCalendarTime(time_zone_rule, time, calendar);
858 } else {
859 return ERROR_UNINITIALIZED_CLOCK;
860 }
861}
862
863ResultCode TimeZoneManager::ParseTimeZoneRuleBinary(TimeZoneRule& rules,
864 FileSys::VirtualFile& vfs_file) const {
865 if (!ParseTimeZoneBinary(rules, vfs_file)) {
866 return ERROR_TIME_ZONE_CONVERSION_FAILED;
867 }
868 return RESULT_SUCCESS;
869}
870
871ResultCode TimeZoneManager::ToPosixTime(const TimeZoneRule& rules,
872 const CalendarTime& calendar_time, s64& posix_time) const {
873 posix_time = 0;
874
875 CalendarTimeInternal internal_time{};
876 internal_time.year = calendar_time.year;
877 internal_time.month = calendar_time.month - 1; // Internal impl. uses 0-indexed month
878 internal_time.day = calendar_time.day;
879 internal_time.hour = calendar_time.hour;
880 internal_time.minute = calendar_time.minute;
881 internal_time.second = calendar_time.second;
882
883 s32 hour{internal_time.hour};
884 s32 minute{internal_time.minute};
885 if (!SafeNormalize(hour, minute, minutes_per_hour)) {
886 return ERROR_OVERFLOW;
887 }
888 internal_time.minute = static_cast<s8>(minute);
889
890 s32 day{internal_time.day};
891 if (!SafeNormalize(day, hour, hours_per_day)) {
892 return ERROR_OVERFLOW;
893 }
894 internal_time.day = static_cast<s8>(day);
895 internal_time.hour = static_cast<s8>(hour);
896
897 s64 year{internal_time.year};
898 s64 month{internal_time.month};
899 if (!SafeNormalize(year, month, months_per_year)) {
900 return ERROR_OVERFLOW;
901 }
902 internal_time.month = static_cast<s8>(month);
903
904 if (!SafeAdd(year, year_base)) {
905 return ERROR_OVERFLOW;
906 }
907
908 while (day <= 0) {
909 if (!SafeAdd(year, -1)) {
910 return ERROR_OVERFLOW;
911 }
912 s64 temp_year{year};
913 if (1 < internal_time.month) {
914 ++temp_year;
915 }
916 day += static_cast<s32>(GetYearLengthInDays(temp_year));
917 }
918
919 while (day > days_per_leap_year) {
920 s64 temp_year{year};
921 if (1 < internal_time.month) {
922 temp_year++;
923 }
924 day -= static_cast<s32>(GetYearLengthInDays(temp_year));
925 if (!SafeAdd(year, 1)) {
926 return ERROR_OVERFLOW;
927 }
928 }
929
930 while (true) {
931 const s32 month_length{GetMonthLength(IsLeapYear(year), internal_time.month)};
932 if (day <= month_length) {
933 break;
934 }
935 day -= month_length;
936 internal_time.month++;
937 if (internal_time.month >= months_per_year) {
938 internal_time.month = 0;
939 if (!SafeAdd(year, 1)) {
940 return ERROR_OVERFLOW;
941 }
942 }
943 }
944 internal_time.day = static_cast<s8>(day);
945
946 if (!SafeAdd(year, -year_base)) {
947 return ERROR_OVERFLOW;
948 }
949 internal_time.year = year;
950
951 s32 saved_seconds{};
952 if (internal_time.second >= 0 && internal_time.second < seconds_per_minute) {
953 saved_seconds = 0;
954 } else if (year + year_base < epoch_year) {
955 s32 second{internal_time.second};
956 if (!SafeAdd(second, 1 - seconds_per_minute)) {
957 return ERROR_OVERFLOW;
958 }
959 saved_seconds = second;
960 internal_time.second = 1 - seconds_per_minute;
961 } else {
962 saved_seconds = internal_time.second;
963 internal_time.second = 0;
964 }
965
966 s64 low{LLONG_MIN};
967 s64 high{LLONG_MAX};
968 while (true) {
969 s64 pivot{low / 2 + high / 2};
970 if (pivot < low) {
971 pivot = low;
972 } else if (pivot > high) {
973 pivot = high;
974 }
975 s32 direction{};
976 CalendarTimeInternal candidate_calendar_time{};
977 CalendarAdditionalInfo unused{};
978 if (ToCalendarTimeInternal(rules, pivot, candidate_calendar_time, unused) !=
979 RESULT_SUCCESS) {
980 if (pivot > 0) {
981 direction = 1;
982 } else {
983 direction = -1;
984 }
985 } else {
986 direction = candidate_calendar_time.Compare(internal_time);
987 }
988 if (!direction) {
989 const s64 time_result{pivot + saved_seconds};
990 if ((time_result < pivot) != (saved_seconds < 0)) {
991 return ERROR_OVERFLOW;
992 }
993 posix_time = time_result;
994 break;
995 } else {
996 if (pivot == low) {
997 if (pivot == LLONG_MAX) {
998 return ERROR_TIME_NOT_FOUND;
999 }
1000 pivot++;
1001 low++;
1002 } else if (pivot == high) {
1003 if (pivot == LLONG_MIN) {
1004 return ERROR_TIME_NOT_FOUND;
1005 }
1006 pivot--;
1007 high--;
1008 }
1009 if (low > high) {
1010 return ERROR_TIME_NOT_FOUND;
1011 }
1012 if (direction > 0) {
1013 high = pivot;
1014 } else {
1015 low = pivot;
1016 }
1017 }
1018 }
1019 return RESULT_SUCCESS;
1020}
1021
1022ResultCode TimeZoneManager::GetDeviceLocationName(LocationName& value) const {
1023 if (!is_initialized) {
1024 return ERROR_UNINITIALIZED_CLOCK;
1025 }
1026 std::memcpy(value.data(), device_location_name.c_str(), device_location_name.size());
1027 return RESULT_SUCCESS;
1028}
1029
1030} // 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
new file mode 100644
index 000000000..7c6f975ae
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_manager.h
@@ -0,0 +1,53 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8
9#include "common/common_types.h"
10#include "core/file_sys/vfs_types.h"
11#include "core/hle/service/time/clock_types.h"
12#include "core/hle/service/time/time_zone_types.h"
13
14namespace Service::Time::TimeZone {
15
16class TimeZoneManager final {
17public:
18 TimeZoneManager();
19 ~TimeZoneManager();
20
21 void SetTotalLocationNameCount(std::size_t value) {
22 total_location_name_count = value;
23 }
24
25 void SetTimeZoneRuleVersion(const u128& value) {
26 time_zone_rule_version = value;
27 }
28
29 void MarkAsInitialized() {
30 is_initialized = true;
31 }
32
33 ResultCode SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
34 FileSys::VirtualFile& vfs_file);
35 ResultCode SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
36 ResultCode GetDeviceLocationName(TimeZone::LocationName& value) const;
37 ResultCode ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
38 ResultCode ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
39 ResultCode ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
40 ResultCode ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time,
41 s64& posix_time) const;
42
43private:
44 bool is_initialized{};
45 TimeZoneRule time_zone_rule{};
46 std::string device_location_name{"GMT"};
47 u128 time_zone_rule_version{};
48 std::size_t total_location_name_count{};
49 Clock::SteadyClockTimePoint time_zone_update_time_point{
50 Clock::SteadyClockTimePoint::GetRandom()};
51};
52
53} // namespace Service::Time::TimeZone
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
new file mode 100644
index 000000000..1566e778e
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -0,0 +1,148 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/time/time_zone_content_manager.h"
8#include "core/hle/service/time/time_zone_service.h"
9#include "core/hle/service/time/time_zone_types.h"
10
11namespace Service::Time {
12
13ITimeZoneService ::ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_content_manager)
14 : ServiceFramework("ITimeZoneService"), time_zone_content_manager{time_zone_content_manager} {
15 static const FunctionInfo functions[] = {
16 {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
17 {1, nullptr, "SetDeviceLocationName"},
18 {2, nullptr, "GetTotalLocationNameCount"},
19 {3, nullptr, "LoadLocationNameList"},
20 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
21 {5, nullptr, "GetTimeZoneRuleVersion"},
22 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
23 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
24 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
25 {202, nullptr, "ToPosixTimeWithMyRule"},
26 };
27 RegisterHandlers(functions);
28}
29
30void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
31 LOG_DEBUG(Service_Time, "called");
32
33 TimeZone::LocationName location_name{};
34 if (const ResultCode result{
35 time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)};
36 result != RESULT_SUCCESS) {
37 IPC::ResponseBuilder rb{ctx, 2};
38 rb.Push(result);
39 return;
40 }
41
42 IPC::ResponseBuilder rb{ctx, (sizeof(location_name) / 4) + 2};
43 rb.Push(RESULT_SUCCESS);
44 rb.PushRaw(location_name);
45}
46
47void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
48 IPC::RequestParser rp{ctx};
49 const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
50
51 std::string location_name;
52 for (const auto& byte : raw_location_name) {
53 // Strip extra bytes
54 if (byte == '\0') {
55 break;
56 }
57 location_name.push_back(byte);
58 }
59
60 LOG_DEBUG(Service_Time, "called, location_name={}", location_name);
61
62 TimeZone::TimeZoneRule time_zone_rule{};
63 if (const ResultCode result{
64 time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
65 result != RESULT_SUCCESS) {
66 IPC::ResponseBuilder rb{ctx, 2};
67 rb.Push(result);
68 return;
69 }
70
71 std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule));
72 std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule));
73 ctx.WriteBuffer(time_zone_rule_outbuffer);
74
75 IPC::ResponseBuilder rb{ctx, 2};
76 rb.Push(RESULT_SUCCESS);
77}
78
79void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) {
80 IPC::RequestParser rp{ctx};
81 const auto posix_time{rp.Pop<s64>()};
82
83 LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
84
85 TimeZone::TimeZoneRule time_zone_rule{};
86 const auto buffer{ctx.ReadBuffer()};
87 std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
88
89 TimeZone::CalendarInfo calendar_info{};
90 if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime(
91 time_zone_rule, posix_time, calendar_info)};
92 result != RESULT_SUCCESS) {
93 IPC::ResponseBuilder rb{ctx, 2};
94 rb.Push(result);
95 return;
96 }
97
98 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
99 rb.Push(RESULT_SUCCESS);
100 rb.PushRaw(calendar_info);
101}
102
103void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
104 IPC::RequestParser rp{ctx};
105 const auto posix_time{rp.Pop<s64>()};
106
107 LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
108
109 TimeZone::CalendarInfo calendar_info{};
110 if (const ResultCode result{
111 time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules(
112 posix_time, calendar_info)};
113 result != RESULT_SUCCESS) {
114 IPC::ResponseBuilder rb{ctx, 2};
115 rb.Push(result);
116 return;
117 }
118
119 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
120 rb.Push(RESULT_SUCCESS);
121 rb.PushRaw(calendar_info);
122}
123
124void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
125 LOG_DEBUG(Service_Time, "called");
126
127 IPC::RequestParser rp{ctx};
128 const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
129 TimeZone::TimeZoneRule time_zone_rule{};
130 std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule));
131
132 s64 posix_time{};
133 if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime(
134 time_zone_rule, calendar_time, posix_time)};
135 result != RESULT_SUCCESS) {
136 IPC::ResponseBuilder rb{ctx, 2};
137 rb.Push(result);
138 return;
139 }
140
141 // TODO(bunnei): Handle multiple times
142 IPC::ResponseBuilder rb{ctx, 3};
143 rb.Push(RESULT_SUCCESS);
144 rb.PushRaw<u32>(1); // Number of times we're returning
145 ctx.WriteBuffer(&posix_time, sizeof(s64));
146}
147
148} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_zone_service.h b/src/core/hle/service/time/time_zone_service.h
new file mode 100644
index 000000000..a92b4312b
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_service.h
@@ -0,0 +1,30 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9namespace Service::Time {
10
11namespace TimeZone {
12class TimeZoneContentManager;
13}
14
15class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
16public:
17 explicit ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_manager);
18
19private:
20 void GetDeviceLocationName(Kernel::HLERequestContext& ctx);
21 void LoadTimeZoneRule(Kernel::HLERequestContext& ctx);
22 void ToCalendarTime(Kernel::HLERequestContext& ctx);
23 void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx);
24 void ToPosixTime(Kernel::HLERequestContext& ctx);
25
26private:
27 TimeZone::TimeZoneContentManager& time_zone_content_manager;
28};
29
30} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_zone_types.h b/src/core/hle/service/time/time_zone_types.h
new file mode 100644
index 000000000..9be15b53e
--- /dev/null
+++ b/src/core/hle/service/time/time_zone_types.h
@@ -0,0 +1,87 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/common_funcs.h"
10#include "common/common_types.h"
11#include "common/swap.h"
12
13namespace Service::Time::TimeZone {
14
15using LocationName = std::array<char, 0x24>;
16
17/// https://switchbrew.org/wiki/Glue_services#ttinfo
18struct TimeTypeInfo {
19 s32 gmt_offset{};
20 u8 is_dst{};
21 INSERT_PADDING_BYTES(3);
22 s32 abbreviation_list_index{};
23 u8 is_standard_time_daylight{};
24 u8 is_gmt{};
25 INSERT_PADDING_BYTES(2);
26};
27static_assert(sizeof(TimeTypeInfo) == 0x10, "TimeTypeInfo is incorrect size");
28
29/// https://switchbrew.org/wiki/Glue_services#TimeZoneRule
30struct TimeZoneRule {
31 s32 time_count{};
32 s32 type_count{};
33 s32 char_count{};
34 u8 go_back{};
35 u8 go_ahead{};
36 INSERT_PADDING_BYTES(2);
37 std::array<s64, 1000> ats{};
38 std::array<s8, 1000> types{};
39 std::array<TimeTypeInfo, 128> ttis{};
40 std::array<char, 512> chars{};
41 s32 default_type{};
42 INSERT_PADDING_BYTES(0x12C4);
43};
44static_assert(sizeof(TimeZoneRule) == 0x4000, "TimeZoneRule is incorrect size");
45
46/// https://switchbrew.org/wiki/Glue_services#CalendarAdditionalInfo
47struct CalendarAdditionalInfo {
48 u32 day_of_week{};
49 u32 day_of_year{};
50 std::array<char, 8> timezone_name;
51 u32 is_dst{};
52 s32 gmt_offset{};
53};
54static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo is incorrect size");
55
56/// https://switchbrew.org/wiki/Glue_services#CalendarTime
57struct CalendarTime {
58 s16 year{};
59 s8 month{};
60 s8 day{};
61 s8 hour{};
62 s8 minute{};
63 s8 second{};
64 INSERT_PADDING_BYTES(1);
65};
66static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size");
67
68struct CalendarInfo {
69 CalendarTime time{};
70 CalendarAdditionalInfo additiona_info{};
71};
72static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size");
73
74struct TzifHeader {
75 u32_be magic{};
76 u8 version{};
77 INSERT_PADDING_BYTES(15);
78 s32_be ttis_gmt_count{};
79 s32_be ttis_std_count{};
80 s32_be leap_count{};
81 s32_be time_count{};
82 s32_be type_count{};
83 s32_be char_count{};
84};
85static_assert(sizeof(TzifHeader) == 0x2C, "TzifHeader is incorrect size");
86
87} // namespace Service::Time::TimeZone
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 1d1f780e7..58dfa8033 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -91,6 +91,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
91 regs.rasterize_enable = 1; 91 regs.rasterize_enable = 1;
92 regs.rt_separate_frag_data = 1; 92 regs.rt_separate_frag_data = 1;
93 regs.framebuffer_srgb = 1; 93 regs.framebuffer_srgb = 1;
94 regs.cull.front_face = Maxwell3D::Regs::Cull::FrontFace::ClockWise;
94 95
95 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true; 96 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
96 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true; 97 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 2e0536bf6..b155dfb49 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -191,8 +191,7 @@ UniquePipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& render
191 const vk::PipelineRasterizationStateCreateInfo rasterizer_ci( 191 const vk::PipelineRasterizationStateCreateInfo rasterizer_ci(
192 {}, rs.depth_clamp_enable, false, vk::PolygonMode::eFill, 192 {}, rs.depth_clamp_enable, false, vk::PolygonMode::eFill,
193 rs.cull_enable ? MaxwellToVK::CullFace(rs.cull_face) : vk::CullModeFlagBits::eNone, 193 rs.cull_enable ? MaxwellToVK::CullFace(rs.cull_face) : vk::CullModeFlagBits::eNone,
194 rs.cull_enable ? MaxwellToVK::FrontFace(rs.front_face) : vk::FrontFace::eCounterClockwise, 194 MaxwellToVK::FrontFace(rs.front_face), rs.depth_bias_enable, 0.0f, 0.0f, 0.0f, 1.0f);
195 rs.depth_bias_enable, 0.0f, 0.0f, 0.0f, 1.0f);
196 195
197 const vk::PipelineMultisampleStateCreateInfo multisampling_ci( 196 const vk::PipelineMultisampleStateCreateInfo multisampling_ci(
198 {}, vk::SampleCountFlagBits::e1, false, 0.0f, nullptr, false, false); 197 {}, vk::SampleCountFlagBits::e1, false, 0.0f, nullptr, false, false);
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 0cf97cafa..dd6d2ef03 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1796,9 +1796,17 @@ private:
1796 return {}; 1796 return {};
1797 } 1797 }
1798 1798
1799 Expression UAtomicAdd(Operation) { 1799 Expression UAtomicAdd(Operation operation) {
1800 UNIMPLEMENTED(); 1800 const auto& smem = std::get<SmemNode>(*operation[0]);
1801 return {}; 1801 Id address = AsUint(Visit(smem.GetAddress()));
1802 address = OpShiftRightLogical(t_uint, address, Constant(t_uint, 2U));
1803 const Id pointer = OpAccessChain(t_smem_uint, shared_memory, address);
1804
1805 const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
1806 const Id semantics = Constant(t_uint, 0U);
1807
1808 const Id value = AsUint(Visit(operation[1]));
1809 return {OpAtomicIAdd(t_uint, pointer, scope, semantics, value), Type::Uint};
1802 } 1810 }
1803 1811
1804 Expression Branch(Operation operation) { 1812 Expression Branch(Operation operation) {
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 25b2e1b05..8497eaa14 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -73,11 +73,11 @@ void ConfigureDialog::RetranslateUI() {
73Q_DECLARE_METATYPE(QList<QWidget*>); 73Q_DECLARE_METATYPE(QList<QWidget*>);
74 74
75void ConfigureDialog::PopulateSelectionList() { 75void ConfigureDialog::PopulateSelectionList() {
76 const std::array<std::pair<QString, QList<QWidget*>>, 4> items{ 76 const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
77 {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->gameListTab}}, 77 {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->gameListTab}},
78 {tr("System"), 78 {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}},
79 {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab, ui->audioTab}},
80 {tr("Graphics"), {ui->graphicsTab}}, 79 {tr("Graphics"), {ui->graphicsTab}},
80 {tr("Audio"), {ui->audioTab}},
81 {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}, 81 {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}},
82 }; 82 };
83 83