mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
registration: Add RegisteredCacheUnion
Aggregates multiple caches into one interface
This commit is contained in:
parent
d2caf4af7d
commit
9951f6d054
4 changed files with 164 additions and 0 deletions
|
@ -280,6 +280,14 @@ VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const
|
||||||
return GetEntryUnparsed(entry.title_id, entry.type);
|
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 {
|
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
|
||||||
const auto id = GetNcaIDFromMetadata(title_id, type);
|
const auto id = GetNcaIDFromMetadata(title_id, type);
|
||||||
if (id == boost::none)
|
if (id == boost::none)
|
||||||
|
@ -498,4 +506,110 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) {
|
||||||
kv.second.GetTitleID() == cnmt.GetTitleID();
|
kv.second.GetTitleID() == cnmt.GetTitleID();
|
||||||
}) != yuzu_meta.end();
|
}) != 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
|
} // namespace FileSys
|
||||||
|
|
|
@ -43,6 +43,10 @@ struct RegisteredCacheEntry {
|
||||||
std::string DebugInfo() const;
|
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.
|
// boost flat_map requires operator< for O(log(n)) lookups.
|
||||||
bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
|
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.)
|
* 4GB splitting can be ignored.)
|
||||||
*/
|
*/
|
||||||
class RegisteredCache {
|
class RegisteredCache {
|
||||||
|
friend class RegisteredCacheUnion;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Parsing function defines the conversion from raw file to NCA. If there are other steps
|
// 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
|
// 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(u64 title_id, ContentRecordType type) const;
|
||||||
bool HasEntry(RegisteredCacheEntry entry) const;
|
bool HasEntry(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
|
boost::optional<u32> GetEntryVersion(u64 title_id) const;
|
||||||
|
|
||||||
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
||||||
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
|
@ -131,4 +139,36 @@ private:
|
||||||
boost::container::flat_map<u64, CNMT> yuzu_meta;
|
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
|
} // namespace FileSys
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "core/hle/service/filesystem/fsp_ldr.h"
|
#include "core/hle/service/filesystem/fsp_ldr.h"
|
||||||
#include "core/hle/service/filesystem/fsp_pr.h"
|
#include "core/hle/service/filesystem/fsp_pr.h"
|
||||||
#include "core/hle/service/filesystem/fsp_srv.h"
|
#include "core/hle/service/filesystem/fsp_srv.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
namespace Service::FileSystem {
|
namespace Service::FileSystem {
|
||||||
|
|
||||||
|
@ -307,6 +308,12 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
|
||||||
return sdmc_factory->Open();
|
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() {
|
std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() {
|
||||||
LOG_TRACE(Service_FS, "Opening System NAND Contents");
|
LOG_TRACE(Service_FS, "Opening System NAND Contents");
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
class BISFactory;
|
class BISFactory;
|
||||||
class RegisteredCache;
|
class RegisteredCache;
|
||||||
|
class RegisteredCacheUnion;
|
||||||
class RomFSFactory;
|
class RomFSFactory;
|
||||||
class SaveDataFactory;
|
class SaveDataFactory;
|
||||||
class SDMCFactory;
|
class SDMCFactory;
|
||||||
|
@ -45,6 +46,8 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
|
||||||
FileSys::SaveDataDescriptor save_struct);
|
FileSys::SaveDataDescriptor save_struct);
|
||||||
ResultVal<FileSys::VirtualDir> OpenSDMC();
|
ResultVal<FileSys::VirtualDir> OpenSDMC();
|
||||||
|
|
||||||
|
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
|
||||||
|
|
||||||
std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents();
|
std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents();
|
||||||
std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents();
|
std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents();
|
||||||
std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents();
|
std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents();
|
||||||
|
|
Loading…
Reference in a new issue