diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 13:26:37 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 13:26:37 -0400 |
| commit | 94e97ed8ddd4d480982eedbbce04533a78bfa65a (patch) | |
| tree | 6af5f2ce71a5c11a73a0a7d7e3aae916ed5af8a1 /src/core/loader | |
| parent | 5da171e8766184678be8204a2295e9b52be3bf9c (diff) | |
loader: give loose ExeFS boots a RomFS and an fs registration
The ExeFS directory loader never set its romfs member and, when used on
its own, never registered the process with the FileSystemController, so
fsp-srv SetCurrentProcess failed with ResultTargetNotFound (2002-1002).
Build the RomFS from a romfs/ directory next to exefs/ (or a .romfs file
in exefs/), and register the process when the loader isn't wrapped by
the NCA/NSP loaders.
Diffstat (limited to 'src/core/loader')
| -rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 5e2ec7e0b9..458e0210a0 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -12,6 +12,7 @@ #include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" +#include "core/file_sys/romfs.h" #include "core/file_sys/romfs_factory.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_process.h" @@ -71,6 +72,30 @@ struct PatchCollection { std::array<s32, 13> module_patcher_indices{}; }; +namespace { + +// RomFS for a loose ExeFS: the first .romfs file next to main, else a romfs/ directory next to +// the exefs/ directory (the usual layout of an extracted title). +FileSys::VirtualFile FindLooseRomFS(const FileSys::VirtualDir& exefs_dir) { + if (exefs_dir == nullptr) { + return nullptr; + } + for (const auto& f : exefs_dir->GetFiles()) { + if (f->GetExtension() == "romfs") { + return f; + } + } + if (const auto parent = exefs_dir->GetParentDirectory()) { + if (const auto romfs_dir = parent->GetSubdirectory("romfs")) { + LOG_INFO(Loader, "Using RomFS directory next to the ExeFS"); + return FileSys::CreateRomFS(romfs_dir); + } + } + return nullptr; +} + +} // namespace + AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, bool override_update_) : AppLoader(std::move(file_)) , override_update(override_update_) @@ -122,6 +147,8 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys FileSys::NACP nacp(nacp_file); name = nacp.GetApplicationName(); } + + romfs = FindLooseRomFS(file_dir); } AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( @@ -129,7 +156,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( : AppLoader(directory->GetFile("main")) , dir(std::move(directory)) , override_update(override_update_) -{} +{ + romfs = FindLooseRomFS(dir); +} FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) { @@ -145,6 +174,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect return {ResultStatus::ErrorAlreadyLoaded, {}}; } + // Loaded directly from a loose ExeFS (not wrapped by the NCA/NSP loaders, which register + // the process with the filesystem controller themselves). + const bool standalone = dir == nullptr; if (dir == nullptr) { if (file == nullptr) { return {ResultStatus::ErrorNullFile, {}}; @@ -266,6 +298,14 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect LOG_DEBUG(Loader, "loaded module {} @ {:#x}", module, load_addr); } + if (standalone) { + // Without this, fsp-srv SetCurrentProcess fails with ResultTargetNotFound. + system.GetFileSystemController().RegisterProcess( + process.GetProcessId(), metadata.GetTitleID(), + std::make_shared<FileSys::RomFSFactory>(*this, system.GetContentProvider(), + system.GetFileSystemController())); + } + is_loaded = true; return {ResultStatus::Success, LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; |
