From 1664c74a6c5a02640bb5f2204b661f94e825d906 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Mon, 14 Jun 2021 21:41:25 -0400 Subject: [PATCH] core: Support LayeredFS mod from SDMC directory Enables loading a mod directly from `[yuzu data directory]/sdmc/atmosphere/contents/[title_id]`. For use with some homebrew mod managers. --- src/core/file_sys/patch_manager.cpp | 31 +++++++++++++++++-- src/core/file_sys/sdmc_factory.cpp | 7 +++++ src/core/file_sys/sdmc_factory.h | 1 + .../hle/service/filesystem/filesystem.cpp | 9 ++++++ src/core/hle/service/filesystem/filesystem.h | 1 + 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 53b8b7ca0d..6f5aa6da29 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -345,8 +345,10 @@ std::vector PatchManager::CreateCheatList( static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type, const Service::FileSystem::FileSystemController& fs_controller) { 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) { + ((load_dir == nullptr || load_dir->GetSize() <= 0) && + (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) { return; } @@ -356,7 +358,10 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t } const auto& disabled = Settings::values.disabled_addons[title_id]; - auto patch_dirs = load_dir->GetSubdirectories(); + std::vector patch_dirs = load_dir->GetSubdirectories(); + if (std::find(disabled.cbegin(), disabled.cend(), "SDMC") == disabled.cend()) { + patch_dirs.push_back(sdmc_load_dir); + } std::sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); @@ -524,6 +529,28 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } } + // SDMC mod directory (LayeredFS) + const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); + if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) { + std::string types; + + const auto exefs_dir = FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"); + if (IsDirValidAndNonEmpty(exefs_dir)) { + bool layeredfs = false; + + if (layeredfs) + AppendCommaIfNotEmpty(types, "LayeredExeFS"); + } + if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "romfs"))) + AppendCommaIfNotEmpty(types, "LayeredFS"); + + if (!types.empty()) { + const auto mod_disabled = + std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); + out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", types); + } + } + // DLC const auto dlc_entries = content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index cb56d8f2db..f4dba8f163 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -27,6 +27,13 @@ ResultVal SDMCFactory::Open() const { return MakeResult(dir); } +VirtualDir SDMCFactory::GetSDMCModificationLoadRoot(u64 title_id) const { + // LayeredFS doesn't work on updates and title id-less homebrew + if (title_id == 0 || (title_id & 0xFFF) == 0x800) + return nullptr; + return GetOrCreateDirectoryRelative(dir, fmt::format("/atmosphere/contents/{:016X}", title_id)); +} + VirtualDir SDMCFactory::GetSDMCContentDirectory() const { return GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents"); } diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 2bb92ba936..c57514938f 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -21,6 +21,7 @@ public: ResultVal Open() const; + VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; VirtualDir GetSDMCContentDirectory() const; RegisteredCache* GetSDMCContents() const; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3c16fe6c71..9191f19fe8 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -703,6 +703,15 @@ FileSys::VirtualDir FileSystemController::GetModificationLoadRoot(u64 title_id) return bis_factory->GetModificationLoadRoot(title_id); } +FileSys::VirtualDir FileSystemController::GetSDMCModificationLoadRoot(u64 title_id) const { + LOG_TRACE(Service_FS, "Opening SDMC mod load root for tid={:016X}", title_id); + + if (sdmc_factory == nullptr) + return nullptr; + + return sdmc_factory->GetSDMCModificationLoadRoot(title_id); +} + FileSys::VirtualDir FileSystemController::GetModificationDumpRoot(u64 title_id) const { LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index b6b1b92207..d387af3cbe 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -115,6 +115,7 @@ public: FileSys::VirtualDir GetContentDirectory(ContentStorageId id) const; FileSys::VirtualDir GetImageDirectory(ImageDirectoryId id) const; + FileSys::VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) const; FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) const;