summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys/registered_cache.h
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2018-08-10 02:52:27 +0200
committerZach Hilman <zachhilman@gmail.com>2018-08-12 04:50:48 +0200
commita91983b11c9aab00065e258ab94b1b99a1f62201 (patch)
tree27dadbb317f8d7653520861ce61dbea53a4d03ff /src/core/file_sys/registered_cache.h
parentfile_sys: Add support for parsing NCA metadata (CNMT) (diff)
downloadyuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar.gz
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar.bz2
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar.lz
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar.xz
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.tar.zst
yuzu-a91983b11c9aab00065e258ab94b1b99a1f62201.zip
Diffstat (limited to 'src/core/file_sys/registered_cache.h')
-rw-r--r--src/core/file_sys/registered_cache.h108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
new file mode 100644
index 000000000..ba2e3403f
--- /dev/null
+++ b/src/core/file_sys/registered_cache.h
@@ -0,0 +1,108 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <map>
+#include <memory>
+#include <string>
+#include <boost/container/flat_map.hpp>
+#include "common/common_funcs.h"
+#include "content_archive.h"
+#include "core/file_sys/vfs.h"
+#include "nca_metadata.h"
+
+namespace FileSys {
+class XCI;
+class CNMT;
+
+using NcaID = std::array<u8, 0x10>;
+using RegisteredCacheParsingFunction = std::function<VirtualFile(const VirtualFile&, const NcaID&)>;
+
+struct RegisteredCacheEntry {
+ u64 title_id;
+ ContentRecordType type;
+
+ std::string DebugInfo() const;
+};
+
+// boost flat_map requires operator< for O(log(n)) lookups.
+bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
+
+/*
+ * A class that catalogues NCAs in the registered directory structure.
+ * Nintendo's registered format follows this structure:
+ *
+ * Root
+ * | 000000XX <- XX is the ____ two digits of the NcaID
+ * | <hash>.nca <- hash is the NcaID (first half of SHA256 over entire file) (folder)
+ * | 00
+ * | 01 <- Actual content split along 4GB boundaries. (optional)
+ *
+ * (This impl also supports substituting the nca dir for an nca file, as that's more convenient when
+ * 4GB splitting can be ignored.)
+ */
+class RegisteredCache {
+public:
+ // Parsing function defines the conversion from raw file to NCA. If there are other steps
+ // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom
+ // parsing function.
+ RegisteredCache(VirtualDir dir,
+ RegisteredCacheParsingFunction parsing_function =
+ [](const VirtualFile& file, const NcaID& id) { return file; });
+
+ void Refresh();
+
+ bool HasEntry(u64 title_id, ContentRecordType type) const;
+ bool HasEntry(RegisteredCacheEntry entry) const;
+
+ VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const;
+ VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const;
+
+ std::shared_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const;
+ std::shared_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
+
+ std::vector<RegisteredCacheEntry> ListEntries() const;
+ // If a parameter is not boost::none, it will be filtered for from all entries.
+ std::vector<RegisteredCacheEntry> ListEntriesFilter(
+ boost::optional<TitleType> title_type = boost::none,
+ boost::optional<ContentRecordType> record_type = boost::none,
+ boost::optional<u64> title_id = boost::none) const;
+
+ // Raw copies all the ncas from the xci to the csache. Does some quick checks to make sure there
+ // is a meta NCA and all of them are accessible.
+ bool InstallEntry(std::shared_ptr<XCI> xci);
+
+ // Due to the fact that we must use Meta-type NCAs to determine the existance 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.
+ bool InstallEntry(std::shared_ptr<NCA> nca, TitleType type);
+
+private:
+ template <typename T>
+ void IterateAllMetadata(std::vector<T>& out,
+ std::function<T(const CNMT&, const ContentRecord&)> proc,
+ std::function<bool(const CNMT&, const ContentRecord&)> filter) const;
+ void AccumulateFiles(std::vector<NcaID>& ids) const;
+ void ProcessFiles(const std::vector<NcaID>& ids);
+ void AccumulateYuzuMeta();
+ boost::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
+ VirtualFile GetFileAtID(NcaID id) const;
+ VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
+ bool RawInstallNCA(std::shared_ptr<NCA> nca, boost::optional<NcaID> override_id = boost::none);
+ bool RawInstallYuzuMeta(const CNMT& cnmt);
+
+ VirtualDir dir;
+ RegisteredCacheParsingFunction parser;
+ // maps tid -> NcaID of meta
+ boost::container::flat_map<u64, NcaID> meta_id;
+ // maps tid -> meta
+ boost::container::flat_map<u64, CNMT> meta;
+ // maps tid -> meta for CNMT in yuzu_meta
+ boost::container::flat_map<u64, CNMT> yuzu_meta;
+};
+
+} // namespace FileSys