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: 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/hle/service/filesystem/filesystem.cpp | 9 +++++++++ src/core/hle/service/filesystem/filesystem.h | 1 + 2 files changed, 10 insertions(+) (limited to 'src/core/hle') diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3c16fe6c7..9191f19fe 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 b6b1b9220..d387af3cb 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; -- cgit v1.2.3 From 844e0114b07f38feaf948d66a1336d350cfa6c6d Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 15 Jun 2021 19:59:10 -0400 Subject: core: Simplify SDMC mod loading If someone else wants to support other mod formats in the SDMC directory, that can be added later. For now, just allow RomFS modding here and force people to do other types of mods the old way. Addresses review comments. Co-authored-by: LC --- src/core/file_sys/patch_manager.cpp | 25 ++++++------------------- src/core/file_sys/sdmc_factory.cpp | 3 ++- src/core/hle/service/filesystem/filesystem.cpp | 3 ++- 3 files changed, 10 insertions(+), 21 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 6f5aa6da2..13d294ad8 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -529,26 +529,13 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } } - // SDMC mod directory (LayeredFS) + // 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) { - 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); - } + if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0 && + IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "romfs"))) { + const auto mod_disabled = + std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); + out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", "LayeredFS"); } // DLC diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index f4dba8f16..7e878123c 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -29,8 +29,9 @@ ResultVal SDMCFactory::Open() const { 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) + if (title_id == 0 || (title_id & 0xFFF) == 0x800) { return nullptr; + } return GetOrCreateDirectoryRelative(dir, fmt::format("/atmosphere/contents/{:016X}", title_id)); } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 9191f19fe..d66e74d3a 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -706,8 +706,9 @@ FileSys::VirtualDir FileSystemController::GetModificationLoadRoot(u64 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) + if (sdmc_factory == nullptr) { return nullptr; + } return sdmc_factory->GetSDMCModificationLoadRoot(title_id); } -- cgit v1.2.3 From 6ac978426c68270ff022e719f7544251d42b19cf Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 28 Jun 2021 00:27:28 -0400 Subject: filesystem: Open a read-only directory for SDMC mods This prevents mod files from being locked due to the read-only share flag in Windows. --- src/core/file_sys/sdmc_factory.cpp | 25 +++++++++++++------------ src/core/file_sys/sdmc_factory.h | 5 +++-- src/core/hle/service/filesystem/filesystem.cpp | 14 +++++++++----- 3 files changed, 25 insertions(+), 19 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index 7e878123c..e5c72cd4d 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -12,19 +12,20 @@ namespace FileSys { constexpr u64 SDMC_TOTAL_SIZE = 0x10000000000; // 1 TiB -SDMCFactory::SDMCFactory(VirtualDir dir_) - : dir(std::move(dir_)), contents(std::make_unique( - GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents/registered"), - [](const VirtualFile& file, const NcaID& id) { - return NAX{file, id}.GetDecrypted(); - })), +SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_) + : sd_dir(std::move(sd_dir_)), sd_mod_dir(std::move(sd_mod_dir_)), + contents(std::make_unique( + GetOrCreateDirectoryRelative(sd_dir, "/Nintendo/Contents/registered"), + [](const VirtualFile& file, const NcaID& id) { + return NAX{file, id}.GetDecrypted(); + })), placeholder(std::make_unique( - GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents/placehld"))) {} + GetOrCreateDirectoryRelative(sd_dir, "/Nintendo/Contents/placehld"))) {} SDMCFactory::~SDMCFactory() = default; ResultVal SDMCFactory::Open() const { - return MakeResult(dir); + return MakeResult(sd_dir); } VirtualDir SDMCFactory::GetSDMCModificationLoadRoot(u64 title_id) const { @@ -32,11 +33,11 @@ VirtualDir SDMCFactory::GetSDMCModificationLoadRoot(u64 title_id) const { if (title_id == 0 || (title_id & 0xFFF) == 0x800) { return nullptr; } - return GetOrCreateDirectoryRelative(dir, fmt::format("/atmosphere/contents/{:016X}", title_id)); + return GetOrCreateDirectoryRelative(sd_mod_dir, fmt::format("/{:016X}", title_id)); } VirtualDir SDMCFactory::GetSDMCContentDirectory() const { - return GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents"); + return GetOrCreateDirectoryRelative(sd_dir, "/Nintendo/Contents"); } RegisteredCache* SDMCFactory::GetSDMCContents() const { @@ -48,11 +49,11 @@ PlaceholderCache* SDMCFactory::GetSDMCPlaceholder() const { } VirtualDir SDMCFactory::GetImageDirectory() const { - return GetOrCreateDirectoryRelative(dir, "/Nintendo/Album"); + return GetOrCreateDirectoryRelative(sd_dir, "/Nintendo/Album"); } u64 SDMCFactory::GetSDMCFreeSpace() const { - return GetSDMCTotalSpace() - dir->GetSize(); + return GetSDMCTotalSpace() - sd_dir->GetSize(); } u64 SDMCFactory::GetSDMCTotalSpace() const { diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index c57514938..3a3d11f3a 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -16,7 +16,7 @@ class PlaceholderCache; /// File system interface to the SDCard archive class SDMCFactory { public: - explicit SDMCFactory(VirtualDir dir); + explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); ~SDMCFactory(); ResultVal Open() const; @@ -33,7 +33,8 @@ public: u64 GetSDMCTotalSpace() const; private: - VirtualDir dir; + VirtualDir sd_dir; + VirtualDir sd_mod_dir; std::unique_ptr contents; std::unique_ptr placeholder; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index d66e74d3a..4a9b13e45 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -743,20 +743,23 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove } using YuzuPath = Common::FS::YuzuPath; + const auto sdmc_dir_path = Common::FS::GetYuzuPath(YuzuPath::SDMCDir); + const auto sdmc_load_dir_path = sdmc_dir_path / "atmosphere/contents"; const auto rw_mode = FileSys::Mode::ReadWrite; auto nand_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode); - auto sd_directory = - vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::SDMCDir), rw_mode); + auto sd_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_dir_path), rw_mode); auto load_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), FileSys::Mode::Read); + auto sd_load_directory = + vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path), FileSys::Mode::Read); auto dump_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode); if (bis_factory == nullptr) { - bis_factory = - std::make_unique(nand_directory, load_directory, dump_directory); + bis_factory = std::make_unique( + nand_directory, std::move(load_directory), std::move(dump_directory)); system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::SysNAND, bis_factory->GetSystemNANDContents()); system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::UserNAND, @@ -769,7 +772,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove } if (sdmc_factory == nullptr) { - sdmc_factory = std::make_unique(std::move(sd_directory)); + sdmc_factory = std::make_unique(std::move(sd_directory), + std::move(sd_load_directory)); system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::SDMC, sdmc_factory->GetSDMCContents()); } -- cgit v1.2.3