diff options
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/content_archive.h | 2 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.cpp | 12 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.h | 4 | ||||
| -rw-r--r-- | src/core/file_sys/ips_layer.cpp | 8 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 47 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.h | 2 | ||||
| -rw-r--r-- | src/core/file_sys/romfs.cpp | 6 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.cpp | 6 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.h | 1 | ||||
| -rw-r--r-- | src/core/file_sys/system_archive/time_zone_binary.cpp | 706 | ||||
| -rw-r--r-- | src/core/file_sys/vfs.h | 16 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_cached.cpp | 63 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_cached.h | 31 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_concat.cpp | 167 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_concat.h | 28 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_layered.cpp | 9 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 232 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.h | 46 |
19 files changed, 530 insertions, 858 deletions
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 7fdc45ea7..20f524f80 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -93,7 +93,7 @@ inline bool IsDirectoryLogoPartition(const VirtualDir& pfs) { pfs->GetFile("StartupMovie.gif") != nullptr; } -// An implementation of VfsDirectory that represents a Nintendo Content Archive (NCA) conatiner. +// An implementation of VfsDirectory that represents a Nintendo Content Archive (NCA) container. // After construction, use GetStatus to determine if the file is valid and ready to be used. class NCA : public ReadOnlyVfsDirectory { public: diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index 50f44f598..cd9ac2e75 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -23,8 +23,8 @@ const std::array<const char*, 16> LANGUAGE_NAMES{{ "Portuguese", "Russian", "Korean", - "Taiwanese", - "Chinese", + "TraditionalChinese", + "SimplifiedChinese", "BrazilianPortuguese", }}; @@ -45,17 +45,17 @@ constexpr std::array<Language, 18> language_to_codes = {{ Language::German, Language::Italian, Language::Spanish, - Language::Chinese, + Language::SimplifiedChinese, Language::Korean, Language::Dutch, Language::Portuguese, Language::Russian, - Language::Taiwanese, + Language::TraditionalChinese, Language::BritishEnglish, Language::CanadianFrench, Language::LatinAmericanSpanish, - Language::Chinese, - Language::Taiwanese, + Language::SimplifiedChinese, + Language::TraditionalChinese, Language::BrazilianPortuguese, }}; diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 6a81873b1..c98efb00d 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -84,8 +84,8 @@ enum class Language : u8 { Portuguese = 10, Russian = 11, Korean = 12, - Taiwanese = 13, - Chinese = 14, + TraditionalChinese = 13, + SimplifiedChinese = 14, BrazilianPortuguese = 15, Default = 255, diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 5aab428bb..efdf18cee 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -41,12 +41,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) { return IPSFileType::Error; } - constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}}; + static constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}}; if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) { return IPSFileType::IPS; } - constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}}; + static constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}}; if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) { return IPSFileType::IPS32; } @@ -55,12 +55,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) { } static bool IsEOF(IPSFileType type, const std::vector<u8>& data) { - constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}}; + static constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}}; if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) { return true; } - constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}}; + static constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}}; return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin()); } diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 4c80e13a9..d3286b352 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -21,9 +21,12 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs.h" +#include "core/file_sys/vfs_cached.h" #include "core/file_sys/vfs_layered.h" #include "core/file_sys/vfs_vector.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/set/set.h" #include "core/loader/loader.h" #include "core/loader/nso.h" #include "core/memory/cheat_engine.h" @@ -150,7 +153,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; - if (load_dir != nullptr && load_dir->GetSize() > 0) { + if (load_dir != nullptr) { const auto load_patch_dirs = load_dir->GetSubdirectories(); patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end()); } @@ -351,8 +354,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || - ((load_dir == nullptr || load_dir->GetSize() <= 0) && - (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) { + (load_dir == nullptr && sdmc_load_dir == nullptr)) { return; } @@ -380,11 +382,11 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t auto romfs_dir = FindSubdirectoryCaseless(subdir, "romfs"); if (romfs_dir != nullptr) - layers.push_back(std::move(romfs_dir)); + layers.push_back(std::make_shared<CachedVfsDirectory>(romfs_dir)); auto ext_dir = FindSubdirectoryCaseless(subdir, "romfs_ext"); if (ext_dir != nullptr) - layers_ext.push_back(std::move(ext_dir)); + layers_ext.push_back(std::make_shared<CachedVfsDirectory>(ext_dir)); } // When there are no layers to apply, return early as there is no need to rebuild the RomFS @@ -493,7 +495,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u // General Mods (LayeredFS and IPS) const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); - if (mod_dir != nullptr && mod_dir->GetSize() > 0) { + if (mod_dir != nullptr) { for (const auto& mod : mod_dir->GetSubdirectories()) { std::string types; @@ -537,7 +539,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u // SDMC mod directory (RomFS LayeredFS) const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); - if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) { + if (sdmc_mod_dir != nullptr) { std::string types; if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) { AppendCommaIfNotEmpty(types, "LayeredExeFS"); @@ -623,8 +625,37 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const { auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file); + // Get language code from settings + const auto language_code = + Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue()); + + // Convert to application language and get priority list + const auto application_language = + Service::NS::ConvertToApplicationLanguage(language_code) + .value_or(Service::NS::ApplicationLanguage::AmericanEnglish); + const auto language_priority_list = + Service::NS::GetApplicationLanguagePriorityList(application_language); + + // Convert to language names + auto priority_language_names = FileSys::LANGUAGE_NAMES; // Copy + if (language_priority_list) { + for (size_t i = 0; i < priority_language_names.size(); ++i) { + // Relies on FileSys::LANGUAGE_NAMES being in the same order as + // Service::NS::ApplicationLanguage + const auto language_index = static_cast<u8>(language_priority_list->at(i)); + + if (language_index < FileSys::LANGUAGE_NAMES.size()) { + priority_language_names[i] = FileSys::LANGUAGE_NAMES[language_index]; + } else { + // Not a catastrophe, unlikely to happen + LOG_WARNING(Loader, "Invalid language index {}", language_index); + } + } + } + + // Get first matching icon VirtualFile icon_file; - for (const auto& language : FileSys::LANGUAGE_NAMES) { + for (const auto& language : priority_language_names) { icon_file = extracted->GetFile(std::string("icon_").append(language).append(".dat")); if (icon_file != nullptr) { break; diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 878d832c2..a6960170c 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -71,7 +71,7 @@ static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bo } static std::string GetCNMTName(TitleType type, u64 title_id) { - constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{ + static constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{ "SystemProgram", "SystemData", "SystemUpdate", diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index 587f8cae8..bd7f53eaf 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -162,7 +162,7 @@ public: InstallResult InstallEntry(const NSP& nsp, bool overwrite_if_exists = false, const VfsCopyFunction& copy = &VfsRawCopy); - // Due to the fact that we must use Meta-type NCAs to determine the existance of files, this + // Due to the fact that we must use Meta-type NCAs to determine the existence of files, this // poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a // dir inside the NAND called 'yuzu_meta' and store the raw CNMT there. // TODO(DarkLordZach): Author real meta-type NCAs and install those. diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp index ddcfe5980..614da2130 100644 --- a/src/core/file_sys/romfs.cpp +++ b/src/core/file_sys/romfs.cpp @@ -9,6 +9,7 @@ #include "core/file_sys/fsmitm_romfsbuild.h" #include "core/file_sys/romfs.h" #include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_cached.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs_vector.h" @@ -132,7 +133,7 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { out = out->GetSubdirectories().front(); } - return out; + return std::make_shared<CachedVfsDirectory>(out); } VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { @@ -140,7 +141,8 @@ VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { return nullptr; RomFSBuildContext ctx{dir, ext}; - return ConcatenatedVfsFile::MakeConcatenatedFile(0, ctx.Build(), dir->GetName()); + auto file_map = ctx.Build(); + return ConcatenatedVfsFile::MakeConcatenatedFile(0, file_map, dir->GetName()); } } // namespace FileSys diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 1567da231..70b36f170 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -82,9 +82,9 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u // Only detect account/device saves from the future location. switch (type) { case SaveDataType::SaveData: - return fmt::format("{}/account/{}/{:016X}/1", space_id_path, uuid.RawString(), title_id); + return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id); case SaveDataType::DeviceSaveData: - return fmt::format("{}/device/{:016X}/1", space_id_path, title_id); + return fmt::format("{}/device/{:016X}/0", space_id_path, title_id); default: return ""; } @@ -172,7 +172,7 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir, // be interpreted as the title id of the current process. if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { if (title_id == 0) { - title_id = system.GetCurrentProcessProgramID(); + title_id = system.GetApplicationProcessProgramID(); } } diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 3226b884a..27f97c725 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -8,6 +8,7 @@ #include <set> #include <vector> #include "common/common_types.h" +#include "core/file_sys/nca_metadata.h" #include "core/file_sys/vfs.h" namespace Core::Crypto { diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp index 85383998d..7c17bbefa 100644 --- a/src/core/file_sys/system_archive/time_zone_binary.cpp +++ b/src/core/file_sys/system_archive/time_zone_binary.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <array> #include <vector> #include "common/swap.h" @@ -9,656 +8,79 @@ #include "core/file_sys/vfs_vector.h" #include "core/hle/service/time/time_zone_types.h" -namespace FileSys::SystemArchive { - -static constexpr std::array<u8, 9633> LOCATION_NAMES{ - 0x43, 0x45, 0x54, 0x0d, 0x0a, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0d, 0x0a, 0x43, 0x75, - 0x62, 0x61, 0x0d, 0x0a, 0x45, 0x45, 0x54, 0x0d, 0x0a, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0d, 0x0a, - 0x45, 0x69, 0x72, 0x65, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, - 0x44, 0x54, 0x0d, 0x0a, 0x47, 0x42, 0x0d, 0x0a, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0d, - 0x0a, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, - 0x2d, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, - 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x48, - 0x53, 0x54, 0x0d, 0x0a, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x49, 0x72, 0x61, - 0x6e, 0x0d, 0x0a, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0d, 0x0a, 0x4a, 0x61, 0x6d, 0x61, 0x69, - 0x63, 0x61, 0x0d, 0x0a, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x4b, 0x77, 0x61, 0x6a, 0x61, - 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x0d, 0x0a, 0x4d, 0x45, 0x54, - 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0d, 0x0a, - 0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0d, 0x0a, 0x4e, 0x5a, 0x0d, 0x0a, 0x4e, 0x5a, 0x2d, 0x43, - 0x48, 0x41, 0x54, 0x0d, 0x0a, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x50, 0x6f, 0x72, - 0x74, 0x75, 0x67, 0x61, 0x6c, 0x0d, 0x0a, 0x50, 0x52, 0x43, 0x0d, 0x0a, 0x50, 0x53, 0x54, 0x38, - 0x50, 0x44, 0x54, 0x0d, 0x0a, 0x52, 0x4f, 0x43, 0x0d, 0x0a, 0x52, 0x4f, 0x4b, 0x0d, 0x0a, 0x53, - 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79, - 0x0d, 0x0a, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, - 0x0d, 0x0a, 0x55, 0x54, 0x43, 0x0d, 0x0a, 0x57, 0x2d, 0x53, 0x55, 0x0d, 0x0a, 0x57, 0x45, 0x54, - 0x0d, 0x0a, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, - 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, - 0x63, 0x63, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, - 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, - 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, - 0x6e, 0x67, 0x75, 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, - 0x6a, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, - 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, - 0x79, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, - 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, - 0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0d, 0x0a, 0x41, 0x66, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x41, - 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x66, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0d, 0x0a, 0x41, - 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0d, 0x0a, - 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0d, - 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0d, 0x0a, - 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62, - 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, - 0x6d, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, - 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0d, - 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, - 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0d, - 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0d, 0x0a, - 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, - 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0d, - 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0d, 0x0a, - 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0d, 0x0a, 0x41, - 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, - 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0d, - 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, - 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79, - 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, - 0x6f, 0x74, 0x74, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, - 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0d, 0x0a, 0x41, 0x66, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x66, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0d, - 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, - 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, - 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, - 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x69, - 0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, - 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, - 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, - 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f, - 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56, - 0x69, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, - 0x67, 0x6f, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, - 0x69, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, - 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, - 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0d, - 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, - 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68, - 0x61, 0x76, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, - 0x73, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, - 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c, - 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, - 0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0d, - 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61, - 0x79, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, - 0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, - 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, - 0x75, 0x70, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, - 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, - 0x6f, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, - 0x75, 0x76, 0x69, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, - 0x61, 0x6c, 0x75, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, - 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, - 0x75, 0x6e, 0x65, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, - 0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, - 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, - 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f, - 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, - 0x6c, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, - 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, - 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, - 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, - 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, - 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, - 0x72, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, - 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, - 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, - 0x68, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, - 0x61, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, - 0x61, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, - 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50, - 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, - 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, - 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, - 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, - 0x52, 0x69, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, - 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, - 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x73, 0x61, 0x72, - 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, - 0x61, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, - 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, - 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68, 0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, - 0x6c, 0x65, 0x6d, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, - 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, - 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, - 0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, - 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, - 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, - 0x6e, 0x74, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, - 0x74, 0x6f, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, - 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, - 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, - 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76, - 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, - 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, - 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, - 0x6a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, - 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, - 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, - 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, - 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, - 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, - 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x0d, 0x0a, - 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, - 0x75, 0x61, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, - 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, - 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, - 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, - 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, - 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54, - 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0d, - 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, - 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61, - 0x6d, 0x61, 0x63, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, - 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, - 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63, - 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, - 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, - 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, - 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, - 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, - 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, - 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6e, 0x74, - 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, - 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, - 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0d, 0x0a, 0x41, 0x6e, - 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0d, - 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, - 0x72, 0x64, 0x6f, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, - 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, - 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, - 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c, - 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, - 0x6f, 0x77, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, - 0x54, 0x72, 0x6f, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, - 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, - 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, - 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, - 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, - 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, - 0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, - 0x72, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, - 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0d, - 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, - 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, - 0x72, 0x75, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, - 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, - 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x43, 0x68, 0x75, 0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, - 0x61, 0x63, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, - 0x63, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0d, - 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, - 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, - 0x67, 0x75, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, - 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x5f, 0x43, - 0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72, - 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61, - 0x6e, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, - 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, - 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65, - 0x6d, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, - 0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, - 0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, - 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, - 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x6f, - 0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, - 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, - 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, - 0x75, 0x77, 0x61, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, - 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, - 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, - 0x73, 0x63, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, - 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, - 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, - 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, - 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, - 0x69, 0x79, 0x61, 0x64, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, - 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, - 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, - 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, - 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, - 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, - 0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, - 0x6d, 0x62, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68, - 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, - 0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x67, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0d, - 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f, 0x72, - 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, - 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, - 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, - 0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, - 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x74, - 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0d, 0x0a, - 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0d, - 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, - 0x65, 0x72, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, - 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, - 0x46, 0x61, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, - 0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, - 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, - 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0d, - 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, - 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, - 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, - 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0d, 0x0a, 0x41, - 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0d, 0x0a, 0x41, 0x75, - 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, - 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, - 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, - 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x75, 0x73, - 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65, 0x72, 0x72, 0x61, 0x0d, - 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69, - 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72, - 0x77, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, - 0x75, 0x63, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, - 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, - 0x61, 0x2f, 0x4c, 0x48, 0x49, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, - 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, - 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0d, 0x0a, - 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, - 0x72, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e, - 0x6f, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, - 0x4e, 0x53, 0x57, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, - 0x65, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, - 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, - 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, - 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0d, 0x0a, 0x41, - 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, - 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x63, - 0x74, 0x6f, 0x72, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, - 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, - 0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, - 0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, - 0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, - 0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, - 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x41, 0x74, 0x6c, - 0x61, 0x6e, 0x74, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x43, 0x65, - 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, - 0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, - 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0d, - 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e, - 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50, 0x61, - 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x53, 0x61, - 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, - 0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0d, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f, - 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x68, 0x69, - 0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, - 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, - 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0d, 0x0a, - 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, - 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, - 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0d, 0x0a, 0x45, - 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, - 0x54, 0x2b, 0x34, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0d, 0x0a, - 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, - 0x4d, 0x54, 0x2b, 0x37, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0d, - 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, - 0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, - 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, - 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, - 0x54, 0x2d, 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, - 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0d, 0x0a, 0x45, 0x74, - 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, - 0x2d, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0d, 0x0a, 0x45, - 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, - 0x54, 0x2d, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0d, 0x0a, - 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, - 0x4d, 0x54, 0x2d, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, - 0x45, 0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x45, - 0x74, 0x63, 0x2f, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x6e, 0x69, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x6c, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0d, 0x0a, - 0x45, 0x74, 0x63, 0x2f, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, - 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, - 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, - 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x45, 0x75, - 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0d, 0x0a, - 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0d, - 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, - 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, - 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, - 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, - 0x69, 0x6e, 0x61, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, - 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, - 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, - 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, - 0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0d, 0x0a, - 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0d, - 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0d, 0x0a, - 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, - 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0d, - 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0d, 0x0a, 0x45, - 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, 0x75, - 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0d, 0x0a, - 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, - 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, - 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x0d, - 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x45, - 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0d, - 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0d, 0x0a, 0x45, - 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0d, 0x0a, 0x45, 0x75, - 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, - 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x52, 0x69, 0x67, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, - 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, - 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, - 0x69, 0x6e, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, - 0x6a, 0x65, 0x76, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, - 0x61, 0x74, 0x6f, 0x76, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, - 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, - 0x6f, 0x66, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, - 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, - 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, - 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69, - 0x72, 0x61, 0x73, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, - 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, - 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, - 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, - 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, - 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, - 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, - 0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, - 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, - 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0d, 0x0a, 0x49, - 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e, - 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0d, 0x0a, - 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e, - 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0d, 0x0a, 0x49, 0x6e, 0x64, - 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0d, 0x0a, 0x49, - 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x68, 0x65, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, - 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0d, 0x0a, 0x49, 0x6e, 0x64, - 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x49, - 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0d, 0x0a, 0x49, - 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x4d, - 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74, 0x65, 0x0d, - 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72, 0x0d, - 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0d, - 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0d, 0x0a, 0x50, - 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0d, - 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, - 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43, - 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, - 0x43, 0x68, 0x75, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, - 0x66, 0x61, 0x74, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, - 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, - 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, - 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, - 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, - 0x6c, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0d, - 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c, - 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, - 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, - 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, - 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, - 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, - 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, - 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0d, 0x0a, 0x50, - 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0d, 0x0a, 0x50, - 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0d, 0x0a, 0x50, 0x61, - 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, - 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0d, 0x0a, - 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0d, 0x0a, 0x50, - 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x0d, - 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69, - 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, - 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, - 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, - 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, - 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, - 0x69, 0x63, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, - 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, - 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, - 0x2f, 0x59, 0x61, 0x70, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0d, - 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53, - 0x2f, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e, - 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e, - 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, - 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x0d, 0x0a, 0x55, 0x53, - 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0d, - 0x0a, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69, 0x67, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53, - 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, - 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, - 0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, - 0x0a}; +#include "nx_tzdb.h" -static VirtualFile GenerateDefaultTimeZoneFile() { - struct TimeZoneInfo { - s64_be at; - std::array<u8, 7> padding1; - std::array<char, 4> time_zone_chars; - std::array<u8, 2> padding2; - std::array<char, 6> time_zone_name; - }; +namespace FileSys::SystemArchive { - VirtualFile file{std::make_shared<VectorVfsFile>( - std::vector<u8>(sizeof(Service::Time::TimeZone::TzifHeader) + sizeof(TimeZoneInfo)), - "GMT")}; +const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&> + tzdb_zoneinfo_dirs = {{"Africa", NxTzdb::africa}, + {"America", NxTzdb::america}, + {"Antarctica", NxTzdb::antarctica}, + {"Arctic", NxTzdb::arctic}, + {"Asia", NxTzdb::asia}, + {"Atlantic", NxTzdb::atlantic}, + {"Australia", NxTzdb::australia}, + {"Brazil", NxTzdb::brazil}, + {"Canada", NxTzdb::canada}, + {"Chile", NxTzdb::chile}, + {"Etc", NxTzdb::etc}, + {"Europe", NxTzdb::europe}, + {"Indian", NxTzdb::indian}, + {"Mexico", NxTzdb::mexico}, + {"Pacific", NxTzdb::pacific}, + {"US", NxTzdb::us}}; - const Service::Time::TimeZone::TzifHeader header{ - .magic = 0x545a6966, - .version = 0x32, - .ttis_gmt_count = 1, - .ttis_std_count = 1, - .time_count = 1, - .type_count = 1, - .char_count = 4, - }; - file->WriteObject(header, 0); +const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&> + tzdb_america_dirs = {{"Argentina", NxTzdb::america_argentina}, + {"Indiana", NxTzdb::america_indiana}, + {"Kentucky", NxTzdb::america_kentucky}, + {"North_Dakota", NxTzdb::america_north_dakota}}; - const TimeZoneInfo time_zone_info{ - .at = 0xf8, - .padding1 = {}, - .time_zone_chars = {'G', 'M', 'T', '\0'}, - .padding2 = {}, - .time_zone_name = {'\n', 'G', 'M', 'T', '0', '\n'}, - }; - file->WriteObject(time_zone_info, sizeof(Service::Time::TimeZone::TzifHeader)); +static void GenerateFiles(std::vector<VirtualFile>& directory, + const std::map<const char*, const std::vector<u8>>& files) { + for (const auto& [filename, data] : files) { + const auto data_copy{data}; + const std::string filename_copy{filename}; + VirtualFile file{ + std::make_shared<VectorVfsFile>(std::move(data_copy), std::move(filename_copy))}; + directory.push_back(file); + } +} - return file; +static std::vector<VirtualFile> GenerateZoneinfoFiles() { + std::vector<VirtualFile> zoneinfo_files; + GenerateFiles(zoneinfo_files, NxTzdb::zoneinfo); + return zoneinfo_files; } VirtualDir TimeZoneBinary() { - std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>( - std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{}, - "zoneinfo")}; - std::vector<VirtualFile> root_files{MakeArrayFile(LOCATION_NAMES, "binaryList.txt")}; + std::vector<VirtualDir> america_sub_dirs; + for (const auto& [dir_name, files] : tzdb_america_dirs) { + std::vector<VirtualFile> vfs_files; + GenerateFiles(vfs_files, files); + america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>( + std::move(vfs_files), std::vector<VirtualDir>{}, dir_name)); + } + + std::vector<VirtualDir> zoneinfo_sub_dirs; + for (const auto& [dir_name, files] : tzdb_zoneinfo_dirs) { + std::vector<VirtualFile> vfs_files; + GenerateFiles(vfs_files, files); + if (dir_name == "America") { + zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>( + std::move(vfs_files), std::move(america_sub_dirs), dir_name)); + } else { + zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>( + std::move(vfs_files), std::vector<VirtualDir>{}, dir_name)); + } + } + + std::vector<VirtualDir> zoneinfo_dir{std::make_shared<VectorVfsDirectory>( + GenerateZoneinfoFiles(), std::move(zoneinfo_sub_dirs), "zoneinfo")}; + std::vector<VirtualFile> root_files; + GenerateFiles(root_files, NxTzdb::base); - return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(root_dirs), + return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(zoneinfo_dir), "data"); } diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 8fc1738a4..a93e21f67 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -45,7 +45,7 @@ public: // Return whether or not the user has write permission on this filesystem. virtual bool IsWritable() const; - // Determine if the entry at path is non-existant, a file, or a directory. + // Determine if the entry at path is non-existent, a file, or a directory. virtual VfsEntryType GetEntryType(std::string_view path) const; // Opens the file with path relative to root. If it doesn't exist, returns nullptr. @@ -58,7 +58,7 @@ public: // Moves the file from old_path to new_path, returning the moved file on success and nullptr on // failure. virtual VirtualFile MoveFile(std::string_view old_path, std::string_view new_path); - // Deletes the file with path relative to root, returing true on success. + // Deletes the file with path relative to root, returning true on success. virtual bool DeleteFile(std::string_view path); // Opens the directory with path relative to root. If it doesn't exist, returns nullptr. @@ -71,7 +71,7 @@ public: // Moves the directory from old_path to new_path, returning the moved directory on success and // nullptr on failure. virtual VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path); - // Deletes the directory with path relative to root, returing true on success. + // Deletes the directory with path relative to root, returning true on success. virtual bool DeleteDirectory(std::string_view path); protected: @@ -144,7 +144,7 @@ public: return Read(reinterpret_cast<u8*>(data), sizeof(T), offset); } - // Writes exactly one byte to offset in file and retuns whether or not the byte was written + // Writes exactly one byte to offset in file and returns whether or not the byte was written // successfully. virtual bool WriteByte(u8 data, std::size_t offset = 0); // Writes a vector of bytes to offset in file and returns the number of bytes successfully @@ -191,13 +191,13 @@ public: VfsDirectory() = default; virtual ~VfsDirectory(); - // Retrives the file located at path as if the current directory was root. Returns nullptr if + // Retrieves the file located at path as if the current directory was root. Returns nullptr if // not found. virtual VirtualFile GetFileRelative(std::string_view path) const; // Calls GetFileRelative(path) on the root of the current directory. virtual VirtualFile GetFileAbsolute(std::string_view path) const; - // Retrives the directory located at path as if the current directory was root. Returns nullptr + // Retrieves the directory located at path as if the current directory was root. Returns nullptr // if not found. virtual VirtualDir GetDirectoryRelative(std::string_view path) const; // Calls GetDirectoryRelative(path) on the root of the current directory. @@ -205,7 +205,7 @@ public: // Returns a vector containing all of the files in this directory. virtual std::vector<VirtualFile> GetFiles() const = 0; - // Returns the file with filename matching name. Returns nullptr if directory dosen't have a + // Returns the file with filename matching name. Returns nullptr if directory doesn't have a // file with name. virtual VirtualFile GetFile(std::string_view name) const; @@ -214,7 +214,7 @@ public: // Returns a vector containing all of the subdirectories in this directory. virtual std::vector<VirtualDir> GetSubdirectories() const = 0; - // Returns the directory with name matching name. Returns nullptr if directory dosen't have a + // Returns the directory with name matching name. Returns nullptr if directory doesn't have a // directory with name. virtual VirtualDir GetSubdirectory(std::string_view name) const; diff --git a/src/core/file_sys/vfs_cached.cpp b/src/core/file_sys/vfs_cached.cpp new file mode 100644 index 000000000..c3154ee81 --- /dev/null +++ b/src/core/file_sys/vfs_cached.cpp @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/vfs_cached.h" +#include "core/file_sys/vfs_types.h" + +namespace FileSys { + +CachedVfsDirectory::CachedVfsDirectory(VirtualDir& source_dir) + : name(source_dir->GetName()), parent(source_dir->GetParentDirectory()) { + for (auto& dir : source_dir->GetSubdirectories()) { + dirs.emplace(dir->GetName(), std::make_shared<CachedVfsDirectory>(dir)); + } + for (auto& file : source_dir->GetFiles()) { + files.emplace(file->GetName(), file); + } +} + +CachedVfsDirectory::~CachedVfsDirectory() = default; + +VirtualFile CachedVfsDirectory::GetFile(std::string_view file_name) const { + auto it = files.find(file_name); + if (it != files.end()) { + return it->second; + } + + return nullptr; +} + +VirtualDir CachedVfsDirectory::GetSubdirectory(std::string_view dir_name) const { + auto it = dirs.find(dir_name); + if (it != dirs.end()) { + return it->second; + } + + return nullptr; +} + +std::vector<VirtualFile> CachedVfsDirectory::GetFiles() const { + std::vector<VirtualFile> out; + for (auto& [file_name, file] : files) { + out.push_back(file); + } + return out; +} + +std::vector<VirtualDir> CachedVfsDirectory::GetSubdirectories() const { + std::vector<VirtualDir> out; + for (auto& [dir_name, dir] : dirs) { + out.push_back(dir); + } + return out; +} + +std::string CachedVfsDirectory::GetName() const { + return name; +} + +VirtualDir CachedVfsDirectory::GetParentDirectory() const { + return parent; +} + +} // namespace FileSys diff --git a/src/core/file_sys/vfs_cached.h b/src/core/file_sys/vfs_cached.h new file mode 100644 index 000000000..113acac12 --- /dev/null +++ b/src/core/file_sys/vfs_cached.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <string_view> +#include <vector> +#include "core/file_sys/vfs.h" + +namespace FileSys { + +class CachedVfsDirectory : public ReadOnlyVfsDirectory { +public: + CachedVfsDirectory(VirtualDir& source_directory); + + ~CachedVfsDirectory() override; + VirtualFile GetFile(std::string_view file_name) const override; + VirtualDir GetSubdirectory(std::string_view dir_name) const override; + std::vector<VirtualFile> GetFiles() const override; + std::vector<VirtualDir> GetSubdirectories() const override; + std::string GetName() const override; + VirtualDir GetParentDirectory() const override; + +private: + std::string name; + VirtualDir parent; + std::map<std::string, VirtualDir, std::less<>> dirs; + std::map<std::string, VirtualFile, std::less<>> files; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index d23623aa0..311a59e5f 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp @@ -10,84 +10,105 @@ namespace FileSys { -static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFile>& map) { - const auto last_valid = --map.end(); - for (auto iter = map.begin(); iter != last_valid;) { - const auto old = iter++; - if (old->first + old->second->GetSize() != iter->first) { +ConcatenatedVfsFile::ConcatenatedVfsFile(ConcatenationMap&& concatenation_map_, std::string&& name_) + : concatenation_map(std::move(concatenation_map_)), name(std::move(name_)) { + DEBUG_ASSERT(this->VerifyContinuity()); +} + +bool ConcatenatedVfsFile::VerifyContinuity() const { + u64 last_offset = 0; + for (auto& entry : concatenation_map) { + if (entry.offset != last_offset) { return false; } - } - - return map.begin()->first == 0; -} -ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name_) - : name(std::move(name_)) { - std::size_t next_offset = 0; - for (const auto& file : files_) { - files.emplace(next_offset, file); - next_offset += file->GetSize(); + last_offset = entry.offset + entry.file->GetSize(); } -} -ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name_) - : files(std::move(files_)), name(std::move(name_)) { - ASSERT(VerifyConcatenationMapContinuity(files)); + return true; } ConcatenatedVfsFile::~ConcatenatedVfsFile() = default; -VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector<VirtualFile> files, - std::string name) { - if (files.empty()) +VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(const std::vector<VirtualFile>& files, + std::string&& name) { + // Fold trivial cases. + if (files.empty()) { return nullptr; - if (files.size() == 1) - return files[0]; + } + if (files.size() == 1) { + return files.front(); + } + + // Make the concatenation map from the input. + std::vector<ConcatenationEntry> concatenation_map; + concatenation_map.reserve(files.size()); + u64 last_offset = 0; + + for (auto& file : files) { + concatenation_map.emplace_back(ConcatenationEntry{ + .offset = last_offset, + .file = file, + }); + + last_offset += file->GetSize(); + } - return VirtualFile(new ConcatenatedVfsFile(std::move(files), std::move(name))); + return VirtualFile(new ConcatenatedVfsFile(std::move(concatenation_map), std::move(name))); } VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, - std::multimap<u64, VirtualFile> files, - std::string name) { - if (files.empty()) + const std::multimap<u64, VirtualFile>& files, + std::string&& name) { + // Fold trivial cases. + if (files.empty()) { return nullptr; - if (files.size() == 1) + } + if (files.size() == 1) { return files.begin()->second; + } + + // Make the concatenation map from the input. + std::vector<ConcatenationEntry> concatenation_map; - const auto last_valid = --files.end(); - for (auto iter = files.begin(); iter != last_valid;) { - const auto old = iter++; - if (old->first + old->second->GetSize() != iter->first) { - files.emplace(old->first + old->second->GetSize(), - std::make_shared<StaticVfsFile>(filler_byte, iter->first - old->first - - old->second->GetSize())); + concatenation_map.reserve(files.size()); + u64 last_offset = 0; + + // Iteration of a multimap is ordered, so offset will be strictly non-decreasing. + for (auto& [offset, file] : files) { + if (offset > last_offset) { + concatenation_map.emplace_back(ConcatenationEntry{ + .offset = last_offset, + .file = std::make_shared<StaticVfsFile>(filler_byte, offset - last_offset), + }); } - } - // Ensure the map starts at offset 0 (start of file), otherwise pad to fill. - if (files.begin()->first != 0) - files.emplace(0, std::make_shared<StaticVfsFile>(filler_byte, files.begin()->first)); + concatenation_map.emplace_back(ConcatenationEntry{ + .offset = offset, + .file = file, + }); - return VirtualFile(new ConcatenatedVfsFile(std::move(files), std::move(name))); + last_offset = offset + file->GetSize(); + } + + return VirtualFile(new ConcatenatedVfsFile(std::move(concatenation_map), std::move(name))); } std::string ConcatenatedVfsFile::GetName() const { - if (files.empty()) { + if (concatenation_map.empty()) { return ""; } if (!name.empty()) { return name; } - return files.begin()->second->GetName(); + return concatenation_map.front().file->GetName(); } std::size_t ConcatenatedVfsFile::GetSize() const { - if (files.empty()) { + if (concatenation_map.empty()) { return 0; } - return files.rbegin()->first + files.rbegin()->second->GetSize(); + return concatenation_map.back().offset + concatenation_map.back().file->GetSize(); } bool ConcatenatedVfsFile::Resize(std::size_t new_size) { @@ -95,10 +116,10 @@ bool ConcatenatedVfsFile::Resize(std::size_t new_size) { } VirtualDir ConcatenatedVfsFile::GetContainingDirectory() const { - if (files.empty()) { + if (concatenation_map.empty()) { return nullptr; } - return files.begin()->second->GetContainingDirectory(); + return concatenation_map.front().file->GetContainingDirectory(); } bool ConcatenatedVfsFile::IsWritable() const { @@ -110,25 +131,51 @@ bool ConcatenatedVfsFile::IsReadable() const { } std::size_t ConcatenatedVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { - auto entry = --files.end(); - for (auto iter = files.begin(); iter != files.end(); ++iter) { - if (iter->first > offset) { - entry = --iter; + const ConcatenationEntry key{ + .offset = offset, + .file = nullptr, + }; + + // Read nothing if the map is empty. + if (concatenation_map.empty()) { + return 0; + } + + // Binary search to find the iterator to the first position we can check. + // It must exist, since we are not empty and are comparing unsigned integers. + auto it = std::prev(std::upper_bound(concatenation_map.begin(), concatenation_map.end(), key)); + u64 cur_length = length; + u64 cur_offset = offset; + + while (cur_length > 0 && it != concatenation_map.end()) { + // Check if we can read the file at this position. + const auto& file = it->file; + const u64 map_offset = it->offset; + const u64 file_size = file->GetSize(); + + if (cur_offset > map_offset + file_size) { + // Entirely out of bounds read. break; } - } - if (entry->first + entry->second->GetSize() <= offset) - return 0; + // Read the file at this position. + const u64 file_seek = cur_offset - map_offset; + const u64 intended_read_size = std::min<u64>(cur_length, file_size - file_seek); + const u64 actual_read_size = + file->Read(data + (cur_offset - offset), intended_read_size, file_seek); + + // Update tracking. + cur_offset += actual_read_size; + cur_length -= actual_read_size; + it++; - const auto read_in = - std::min<u64>(entry->first + entry->second->GetSize() - offset, entry->second->GetSize()); - if (length > read_in) { - return entry->second->Read(data, read_in, offset - entry->first) + - Read(data + read_in, length - read_in, offset + read_in); + // If we encountered a short read, we're done. + if (actual_read_size < intended_read_size) { + break; + } } - return entry->second->Read(data, std::min<u64>(read_in, length), offset - entry->first); + return cur_offset - offset; } std::size_t ConcatenatedVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index 9be0261b6..6b329d545 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h @@ -3,6 +3,7 @@ #pragma once +#include <compare> #include <map> #include <memory> #include "core/file_sys/vfs.h" @@ -12,19 +13,33 @@ namespace FileSys { // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently // read-only. class ConcatenatedVfsFile : public VfsFile { - explicit ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name_); - explicit ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name_); +private: + struct ConcatenationEntry { + u64 offset; + VirtualFile file; + + auto operator<=>(const ConcatenationEntry& other) const { + return this->offset <=> other.offset; + } + }; + using ConcatenationMap = std::vector<ConcatenationEntry>; + + explicit ConcatenatedVfsFile(std::vector<ConcatenationEntry>&& concatenation_map, + std::string&& name); + bool VerifyContinuity() const; public: ~ConcatenatedVfsFile() override; /// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases. - static VirtualFile MakeConcatenatedFile(std::vector<VirtualFile> files, std::string name); + static VirtualFile MakeConcatenatedFile(const std::vector<VirtualFile>& files, + std::string&& name); /// Convenience function that turns a map of offsets to files into a concatenated file, filling /// gaps with a given filler byte. - static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::multimap<u64, VirtualFile> files, - std::string name); + static VirtualFile MakeConcatenatedFile(u8 filler_byte, + const std::multimap<u64, VirtualFile>& files, + std::string&& name); std::string GetName() const override; std::size_t GetSize() const override; @@ -37,8 +52,7 @@ public: bool Rename(std::string_view new_name) override; private: - // Maps starting offset to file -- more efficient. - std::multimap<u64, VirtualFile> files; + ConcatenationMap concatenation_map; std::string name; }; diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp index da05dd395..3e6426afc 100644 --- a/src/core/file_sys/vfs_layered.cpp +++ b/src/core/file_sys/vfs_layered.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> +#include <set> #include <utility> #include "core/file_sys/vfs_layered.h" @@ -58,11 +59,13 @@ std::string LayeredVfsDirectory::GetFullPath() const { std::vector<VirtualFile> LayeredVfsDirectory::GetFiles() const { std::vector<VirtualFile> out; + std::set<std::string, std::less<>> out_names; + for (const auto& layer : dirs) { for (const auto& file : layer->GetFiles()) { - if (std::find_if(out.begin(), out.end(), [&file](const VirtualFile& comp) { - return comp->GetName() == file->GetName(); - }) == out.end()) { + auto file_name = file->GetName(); + if (!out_names.contains(file_name)) { + out_names.emplace(std::move(file_name)); out.push_back(file); } } diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index cc0076238..b0515ec05 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -10,6 +10,7 @@ #include "common/fs/fs.h" #include "common/fs/path_util.h" #include "common/logging/log.h" +#include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" // For FileTimeStampRaw @@ -25,6 +26,8 @@ namespace FS = Common::FS; namespace { +constexpr size_t MaxOpenFiles = 512; + constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) { switch (mode) { case Mode::Read: @@ -70,31 +73,42 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { return VfsEntryType::File; } -VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { +VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size, + Mode perms) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); + std::scoped_lock lk{list_lock}; - if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) { - const auto& weak = weak_iter->second; - - if (!weak.expired()) { - return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); + if (auto it = cache.find(path); it != cache.end()) { + if (auto file = it->second.lock(); file) { + return file; } } - auto backing = FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); - - if (!backing) { + if (!size && !FS::IsFile(path)) { return nullptr; } - cache.insert_or_assign(path, std::move(backing)); + auto reference = std::make_unique<FileReference>(); + this->InsertReferenceIntoListLocked(*reference); - // Cannot use make_shared as RealVfsFile constructor is private - return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); + auto file = std::shared_ptr<RealVfsFile>( + new RealVfsFile(*this, std::move(reference), path, perms, size)); + cache[path] = file; + + return file; +} + +VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { + return OpenFileFromEntry(path_, {}, perms); } VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); + { + std::scoped_lock lk{list_lock}; + cache.erase(path); + } + // Current usages of CreateFile expect to delete the contents of an existing file. if (FS::IsFile(path)) { FS::IOFile temp{path, FS::FileAccessMode::Write, FS::FileType::BinaryFile}; @@ -123,51 +137,28 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); - const auto cached_file_iter = cache.find(old_path); - - if (cached_file_iter != cache.cend()) { - auto file = cached_file_iter->second.lock(); - - if (!cached_file_iter->second.expired()) { - file->Close(); - } - - if (!FS::RenameFile(old_path, new_path)) { - return nullptr; - } - + { + std::scoped_lock lk{list_lock}; cache.erase(old_path); - file->Open(new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile); - if (file->IsOpen()) { - cache.insert_or_assign(new_path, std::move(file)); - } else { - LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path); - } - } else { - ASSERT(false); + cache.erase(new_path); + } + if (!FS::RenameFile(old_path, new_path)) { return nullptr; } - return OpenFile(new_path, Mode::ReadWrite); } bool RealVfsFilesystem::DeleteFile(std::string_view path_) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); - const auto cached_iter = cache.find(path); - - if (cached_iter != cache.cend()) { - if (!cached_iter->second.expired()) { - cached_iter->second.lock()->Close(); - } + { + std::scoped_lock lk{list_lock}; cache.erase(path); } - return FS::RemoveFile(path); } VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); - // Cannot use make_shared as RealVfsDirectory constructor is private return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); } @@ -176,7 +167,6 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms if (!FS::CreateDirs(path)) { return nullptr; } - // Cannot use make_shared as RealVfsDirectory constructor is private return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); } @@ -194,73 +184,112 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, if (!FS::RenameDir(old_path, new_path)) { return nullptr; } + return OpenDirectory(new_path, Mode::ReadWrite); +} - for (auto& kv : cache) { - // If the path in the cache doesn't start with old_path, then bail on this file. - if (kv.first.rfind(old_path, 0) != 0) { - continue; - } +bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { + const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); + return FS::RemoveDirRecursively(path); +} - const auto file_old_path = - FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); - auto file_new_path = FS::SanitizePath(new_path + '/' + kv.first.substr(old_path.size()), - FS::DirectorySeparator::PlatformDefault); - const auto& cached = cache[file_old_path]; +std::unique_lock<std::mutex> RealVfsFilesystem::RefreshReference(const std::string& path, + Mode perms, + FileReference& reference) { + std::unique_lock lk{list_lock}; - if (cached.expired()) { - continue; - } + // Temporarily remove from list. + this->RemoveReferenceFromListLocked(reference); + + // Restore file if needed. + if (!reference.file) { + this->EvictSingleReferenceLocked(); - auto file = cached.lock(); - cache.erase(file_old_path); - file->Open(file_new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile); - if (file->IsOpen()) { - cache.insert_or_assign(std::move(file_new_path), std::move(file)); - } else { - LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", file_new_path); + reference.file = + FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); + if (reference.file) { + num_open_files++; } } - return OpenDirectory(new_path, Mode::ReadWrite); + // Reinsert into list. + this->InsertReferenceIntoListLocked(reference); + + return lk; } -bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { - const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); +void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) { + std::scoped_lock lk{list_lock}; - for (auto& kv : cache) { - // If the path in the cache doesn't start with path, then bail on this file. - if (kv.first.rfind(path, 0) != 0) { - continue; - } + // Remove from list. + this->RemoveReferenceFromListLocked(*reference); - const auto& entry = cache[kv.first]; - if (!entry.expired()) { - entry.lock()->Close(); - } + // Close the file. + if (reference->file) { + reference->file.reset(); + num_open_files--; + } +} - cache.erase(kv.first); +void RealVfsFilesystem::EvictSingleReferenceLocked() { + if (num_open_files < MaxOpenFiles || open_references.empty()) { + return; } - return FS::RemoveDirRecursively(path); + // Get and remove from list. + auto& reference = open_references.back(); + this->RemoveReferenceFromListLocked(reference); + + // Close the file. + if (reference.file) { + reference.file.reset(); + num_open_files--; + } + + // Reinsert into closed list. + this->InsertReferenceIntoListLocked(reference); +} + +void RealVfsFilesystem::InsertReferenceIntoListLocked(FileReference& reference) { + if (reference.file) { + open_references.push_front(reference); + } else { + closed_references.push_front(reference); + } } -RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_, - const std::string& path_, Mode perms_) - : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)), - path_components(FS::SplitPathComponents(path_)), perms(perms_) {} +void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference) { + if (reference.file) { + open_references.erase(open_references.iterator_to(reference)); + } else { + closed_references.erase(closed_references.iterator_to(reference)); + } +} -RealVfsFile::~RealVfsFile() = default; +RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, + const std::string& path_, Mode perms_, std::optional<u64> size_) + : base(base_), reference(std::move(reference_)), path(path_), + parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), + size(size_), perms(perms_) {} + +RealVfsFile::~RealVfsFile() { + base.DropReference(std::move(reference)); +} std::string RealVfsFile::GetName() const { return path_components.back(); } std::size_t RealVfsFile::GetSize() const { - return backing->GetSize(); + if (size) { + return *size; + } + return FS::GetSize(path); } bool RealVfsFile::Resize(std::size_t new_size) { - return backing->SetSize(new_size); + size.reset(); + auto lk = base.RefreshReference(path, perms, *reference); + return reference->file ? reference->file->SetSize(new_size) : false; } VirtualDir RealVfsFile::GetContainingDirectory() const { @@ -276,27 +305,26 @@ bool RealVfsFile::IsReadable() const { } std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { - if (!backing->Seek(static_cast<s64>(offset))) { + auto lk = base.RefreshReference(path, perms, *reference); + if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { return 0; } - return backing->ReadSpan(std::span{data, length}); + return reference->file->ReadSpan(std::span{data, length}); } std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { - if (!backing->Seek(static_cast<s64>(offset))) { + size.reset(); + auto lk = base.RefreshReference(path, perms, *reference); + if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { return 0; } - return backing->WriteSpan(std::span{data, length}); + return reference->file->WriteSpan(std::span{data, length}); } bool RealVfsFile::Rename(std::string_view name) { return base.MoveFile(path, parent_path + '/' + std::string(name)) != nullptr; } -void RealVfsFile::Close() { - backing->Close(); -} - // TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if // constexpr' because there is a compile error in the branch not used. @@ -308,10 +336,11 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>( std::vector<VirtualFile> out; - const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { - const auto full_path_string = FS::PathToUTF8String(full_path); + const FS::DirEntryCallable callback = [this, + &out](const std::filesystem::directory_entry& entry) { + const auto full_path_string = FS::PathToUTF8String(entry.path()); - out.emplace_back(base.OpenFile(full_path_string, perms)); + out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms)); return true; }; @@ -329,8 +358,9 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi std::vector<VirtualDir> out; - const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { - const auto full_path_string = FS::PathToUTF8String(full_path); + const FS::DirEntryCallable callback = [this, + &out](const std::filesystem::directory_entry& entry) { + const auto full_path_string = FS::PathToUTF8String(entry.path()); out.emplace_back(base.OpenDirectory(full_path_string, perms)); @@ -482,12 +512,10 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries() std::map<std::string, VfsEntryType, std::less<>> out; - const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) { - const auto filename = FS::PathToUTF8String(full_path.filename()); - + const FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) { + const auto filename = FS::PathToUTF8String(entry.path().filename()); out.insert_or_assign(filename, - FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File); - + entry.is_directory() ? VfsEntryType::Directory : VfsEntryType::File); return true; }; diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index acde1ac89..26ea7df62 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h @@ -3,8 +3,11 @@ #pragma once +#include <map> +#include <mutex> +#include <optional> #include <string_view> -#include <boost/container/flat_map.hpp> +#include "common/intrusive_list.h" #include "core/file_sys/mode.h" #include "core/file_sys/vfs.h" @@ -14,6 +17,13 @@ class IOFile; namespace FileSys { +struct FileReference : public Common::IntrusiveListBaseNode<FileReference> { + std::shared_ptr<Common::FS::IOFile> file{}; +}; + +class RealVfsFile; +class RealVfsDirectory; + class RealVfsFilesystem : public VfsFilesystem { public: RealVfsFilesystem(); @@ -35,10 +45,31 @@ public: bool DeleteDirectory(std::string_view path) override; private: - boost::container::flat_map<std::string, std::weak_ptr<Common::FS::IOFile>> cache; + using ReferenceListType = Common::IntrusiveListBaseTraits<FileReference>::ListType; + std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache; + ReferenceListType open_references; + ReferenceListType closed_references; + std::mutex list_lock; + size_t num_open_files{}; + +private: + friend class RealVfsFile; + std::unique_lock<std::mutex> RefreshReference(const std::string& path, Mode perms, + FileReference& reference); + void DropReference(std::unique_ptr<FileReference>&& reference); + +private: + friend class RealVfsDirectory; + VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size, + Mode perms = Mode::Read); + +private: + void EvictSingleReferenceLocked(); + void InsertReferenceIntoListLocked(FileReference& reference); + void RemoveReferenceFromListLocked(FileReference& reference); }; -// An implmentation of VfsFile that represents a file on the user's computer. +// An implementation of VfsFile that represents a file on the user's computer. class RealVfsFile : public VfsFile { friend class RealVfsDirectory; friend class RealVfsFilesystem; @@ -57,16 +88,15 @@ public: bool Rename(std::string_view name) override; private: - RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing, - const std::string& path, Mode perms = Mode::Read); - - void Close(); + RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, + const std::string& path, Mode perms = Mode::Read, std::optional<u64> size = {}); RealVfsFilesystem& base; - std::shared_ptr<Common::FS::IOFile> backing; + std::unique_ptr<FileReference> reference; std::string path; std::string parent_path; std::vector<std::string> path_components; + std::optional<u64> size; Mode perms; }; |
