registration: Add RegisteredCacheUnion
Aggregates multiple caches into one interface
This commit is contained in:
		
							parent
							
								
									d2caf4af7d
								
							
						
					
					
						commit
						9951f6d054
					
				@ -280,6 +280,14 @@ VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const
 | 
			
		||||
    return GetEntryUnparsed(entry.title_id, entry.type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
 | 
			
		||||
    if (meta.find(title_id) != meta.end())
 | 
			
		||||
        return meta.at(title_id).GetTitleVersion();
 | 
			
		||||
    if (yuzu_meta.find(title_id) != yuzu_meta.end())
 | 
			
		||||
        return yuzu_meta.at(title_id).GetTitleVersion();
 | 
			
		||||
    return boost::none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
 | 
			
		||||
    const auto id = GetNcaIDFromMetadata(title_id, type);
 | 
			
		||||
    if (id == boost::none)
 | 
			
		||||
@ -498,4 +506,110 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) {
 | 
			
		||||
                                   kv.second.GetTitleID() == cnmt.GetTitleID();
 | 
			
		||||
                        }) != yuzu_meta.end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RegisteredCacheUnion::RegisteredCacheUnion(std::vector<std::shared_ptr<RegisteredCache>> caches)
 | 
			
		||||
    : caches(std::move(caches)) {}
 | 
			
		||||
 | 
			
		||||
void RegisteredCacheUnion::Refresh() {
 | 
			
		||||
    for (const auto& c : caches)
 | 
			
		||||
        c->Refresh();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RegisteredCacheUnion::HasEntry(u64 title_id, ContentRecordType type) const {
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        if (c->HasEntry(title_id, type))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const {
 | 
			
		||||
    return HasEntry(entry.title_id, entry.type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        const auto res = c->GetEntryVersion(title_id);
 | 
			
		||||
        if (res != boost::none)
 | 
			
		||||
            return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return boost::none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        const auto res = c->GetEntryUnparsed(title_id, type);
 | 
			
		||||
        if (res != nullptr)
 | 
			
		||||
            return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(RegisteredCacheEntry entry) const {
 | 
			
		||||
    return GetEntryUnparsed(entry.title_id, entry.type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VirtualFile RegisteredCacheUnion::GetEntryRaw(u64 title_id, ContentRecordType type) const {
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        const auto res = c->GetEntryRaw(title_id, type);
 | 
			
		||||
        if (res != nullptr)
 | 
			
		||||
            return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VirtualFile RegisteredCacheUnion::GetEntryRaw(RegisteredCacheEntry entry) const {
 | 
			
		||||
    return GetEntryRaw(entry.title_id, entry.type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(u64 title_id, ContentRecordType type) const {
 | 
			
		||||
    const auto raw = GetEntryRaw(title_id, type);
 | 
			
		||||
    if (raw == nullptr)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    return std::make_shared<NCA>(raw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(RegisteredCacheEntry entry) const {
 | 
			
		||||
    return GetEntry(entry.title_id, entry.type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
 | 
			
		||||
    std::vector<RegisteredCacheEntry> out;
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        c->IterateAllMetadata<RegisteredCacheEntry>(
 | 
			
		||||
            out,
 | 
			
		||||
            [](const CNMT& c, const ContentRecord& r) {
 | 
			
		||||
                return RegisteredCacheEntry{c.GetTitleID(), r.type};
 | 
			
		||||
            },
 | 
			
		||||
            [](const CNMT& c, const ContentRecord& r) { return true; });
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
 | 
			
		||||
    boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
 | 
			
		||||
    boost::optional<u64> title_id) const {
 | 
			
		||||
    std::vector<RegisteredCacheEntry> out;
 | 
			
		||||
    for (const auto& c : caches) {
 | 
			
		||||
        c->IterateAllMetadata<RegisteredCacheEntry>(
 | 
			
		||||
            out,
 | 
			
		||||
            [](const CNMT& c, const ContentRecord& r) {
 | 
			
		||||
                return RegisteredCacheEntry{c.GetTitleID(), r.type};
 | 
			
		||||
            },
 | 
			
		||||
            [&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
 | 
			
		||||
                if (title_type != boost::none && title_type.get() != c.GetType())
 | 
			
		||||
                    return false;
 | 
			
		||||
                if (record_type != boost::none && record_type.get() != r.type)
 | 
			
		||||
                    return false;
 | 
			
		||||
                if (title_id != boost::none && title_id.get() != c.GetTitleID())
 | 
			
		||||
                    return false;
 | 
			
		||||
                return true;
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,10 @@ struct RegisteredCacheEntry {
 | 
			
		||||
    std::string DebugInfo() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
constexpr inline u64 GetUpdateTitleID(u64 base_title_id) {
 | 
			
		||||
    return base_title_id | 0x800;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// boost flat_map requires operator< for O(log(n)) lookups.
 | 
			
		||||
bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
 | 
			
		||||
 | 
			
		||||
@ -60,6 +64,8 @@ bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs)
 | 
			
		||||
 * 4GB splitting can be ignored.)
 | 
			
		||||
 */
 | 
			
		||||
class RegisteredCache {
 | 
			
		||||
    friend class RegisteredCacheUnion;
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@ -74,6 +80,8 @@ public:
 | 
			
		||||
    bool HasEntry(u64 title_id, ContentRecordType type) const;
 | 
			
		||||
    bool HasEntry(RegisteredCacheEntry entry) const;
 | 
			
		||||
 | 
			
		||||
    boost::optional<u32> GetEntryVersion(u64 title_id) const;
 | 
			
		||||
 | 
			
		||||
    VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
 | 
			
		||||
    VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
 | 
			
		||||
 | 
			
		||||
@ -131,4 +139,36 @@ private:
 | 
			
		||||
    boost::container::flat_map<u64, CNMT> yuzu_meta;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Combines multiple RegisteredCaches (i.e. SysNAND, UserNAND, SDMC) into one interface.
 | 
			
		||||
class RegisteredCacheUnion {
 | 
			
		||||
public:
 | 
			
		||||
    explicit RegisteredCacheUnion(std::vector<std::shared_ptr<RegisteredCache>> caches);
 | 
			
		||||
 | 
			
		||||
    void Refresh();
 | 
			
		||||
 | 
			
		||||
    bool HasEntry(u64 title_id, ContentRecordType type) const;
 | 
			
		||||
    bool HasEntry(RegisteredCacheEntry entry) const;
 | 
			
		||||
 | 
			
		||||
    boost::optional<u32> GetEntryVersion(u64 title_id) const;
 | 
			
		||||
 | 
			
		||||
    VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
 | 
			
		||||
    VirtualFile GetEntryUnparsed(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;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<std::shared_ptr<RegisteredCache>> caches;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_ldr.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_pr.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_srv.h"
 | 
			
		||||
#include "filesystem.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::FileSystem {
 | 
			
		||||
 | 
			
		||||
@ -307,6 +308,12 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
 | 
			
		||||
    return sdmc_factory->Open();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
 | 
			
		||||
    return std::make_shared<FileSys::RegisteredCacheUnion>(
 | 
			
		||||
        std::vector<std::shared_ptr<FileSys::RegisteredCache>>{
 | 
			
		||||
            GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() {
 | 
			
		||||
    LOG_TRACE(Service_FS, "Opening System NAND Contents");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
class BISFactory;
 | 
			
		||||
class RegisteredCache;
 | 
			
		||||
class RegisteredCacheUnion;
 | 
			
		||||
class RomFSFactory;
 | 
			
		||||
class SaveDataFactory;
 | 
			
		||||
class SDMCFactory;
 | 
			
		||||
@ -45,6 +46,8 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
 | 
			
		||||
                                            FileSys::SaveDataDescriptor save_struct);
 | 
			
		||||
ResultVal<FileSys::VirtualDir> OpenSDMC();
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents();
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents();
 | 
			
		||||
std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user