summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2024-01-08 00:49:00 -0500
committerGravatar Liam2024-01-11 11:28:52 -0500
commitaae9eea53208fc0924c90ebb1272fcfaa3f23e0c (patch)
tree050ccc76dd2fad3c3f81197aa6435674caeac86f /src
parentMerge pull request #12608 from szepeviktor/typos (diff)
downloadyuzu-aae9eea53208fc0924c90ebb1272fcfaa3f23e0c.tar.gz
yuzu-aae9eea53208fc0924c90ebb1272fcfaa3f23e0c.tar.xz
yuzu-aae9eea53208fc0924c90ebb1272fcfaa3f23e0c.zip
fsp-srv: use program registry for SetCurrentProcess
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/jni/native.cpp6
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/core.cpp1
-rw-r--r--src/core/file_sys/savedata_factory.cpp17
-rw-r--r--src/core/file_sys/savedata_factory.h10
-rw-r--r--src/core/hle/service/am/am.cpp7
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp227
-rw-r--r--src/core/hle/service/filesystem/filesystem.h59
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp55
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h6
-rw-r--r--src/core/hle/service/filesystem/romfs_controller.cpp37
-rw-r--r--src/core/hle/service/filesystem/romfs_controller.h31
-rw-r--r--src/core/hle/service/filesystem/save_data_controller.cpp99
-rw-r--r--src/core/hle/service/filesystem/save_data_controller.h35
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp14
-rw-r--r--src/core/loader/nca.cpp6
-rw-r--r--src/core/loader/nro.cpp6
-rw-r--r--src/core/loader/nsp.cpp3
-rw-r--r--src/core/loader/xci.cpp3
-rw-r--r--src/yuzu/main.cpp8
20 files changed, 362 insertions, 272 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 136c8dee6..8017eb58d 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -770,8 +770,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
770 ASSERT(user_id); 770 ASSERT(user_id);
771 771
772 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( 772 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
773 EmulationSession::GetInstance().System(), vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, 773 {}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 1,
774 FileSys::SaveDataType::SaveData, 1, user_id->AsU128(), 0); 774 user_id->AsU128(), 0);
775 775
776 const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); 776 const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
777 if (!Common::FS::CreateParentDirs(full_path)) { 777 if (!Common::FS::CreateParentDirs(full_path)) {
@@ -878,7 +878,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
878 FileSys::Mode::Read); 878 FileSys::Mode::Read);
879 879
880 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( 880 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
881 system, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 881 {}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
882 program_id, user_id->AsU128(), 0); 882 program_id, user_id->AsU128(), 0);
883 return ToJString(env, user_save_data_path); 883 return ToJString(env, user_save_data_path);
884} 884}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 753f55ebe..293d9647b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -490,6 +490,10 @@ add_library(core STATIC
490 hle/service/filesystem/fsp_pr.h 490 hle/service/filesystem/fsp_pr.h
491 hle/service/filesystem/fsp_srv.cpp 491 hle/service/filesystem/fsp_srv.cpp
492 hle/service/filesystem/fsp_srv.h 492 hle/service/filesystem/fsp_srv.h
493 hle/service/filesystem/romfs_controller.cpp
494 hle/service/filesystem/romfs_controller.h
495 hle/service/filesystem/save_data_controller.cpp
496 hle/service/filesystem/save_data_controller.h
493 hle/service/fgm/fgm.cpp 497 hle/service/fgm/fgm.cpp
494 hle/service/fgm/fgm.h 498 hle/service/fgm/fgm.h
495 hle/service/friend/friend.cpp 499 hle/service/friend/friend.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c063f7719..461eea9c8 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -413,6 +413,7 @@ struct System::Impl {
413 kernel.ShutdownCores(); 413 kernel.ShutdownCores();
414 services.reset(); 414 services.reset();
415 service_manager.reset(); 415 service_manager.reset();
416 fs_controller.Reset();
416 cheat_engine.reset(); 417 cheat_engine.reset();
417 telemetry_session.reset(); 418 telemetry_session.reset();
418 time_manager.Shutdown(); 419 time_manager.Shutdown();
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 12b3bd797..23196cd5f 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -97,8 +97,9 @@ std::string SaveDataAttribute::DebugInfo() const {
97 static_cast<u8>(rank), index); 97 static_cast<u8>(rank), index);
98} 98}
99 99
100SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_directory_) 100SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
101 : dir{std::move(save_directory_)}, system{system_} { 101 VirtualDir save_directory_)
102 : system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} {
102 // Delete all temporary storages 103 // Delete all temporary storages
103 // On hardware, it is expected that temporary storage be empty at first use. 104 // On hardware, it is expected that temporary storage be empty at first use.
104 dir->DeleteSubdirectoryRecursive("temp"); 105 dir->DeleteSubdirectoryRecursive("temp");
@@ -110,7 +111,7 @@ VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribut
110 PrintSaveDataAttributeWarnings(meta); 111 PrintSaveDataAttributeWarnings(meta);
111 112
112 const auto save_directory = 113 const auto save_directory =
113 GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); 114 GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
114 115
115 return dir->CreateDirectoryRelative(save_directory); 116 return dir->CreateDirectoryRelative(save_directory);
116} 117}
@@ -118,7 +119,7 @@ VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribut
118VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { 119VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
119 120
120 const auto save_directory = 121 const auto save_directory =
121 GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); 122 GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
122 123
123 auto out = dir->GetDirectoryRelative(save_directory); 124 auto out = dir->GetDirectoryRelative(save_directory);
124 125
@@ -147,14 +148,14 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
147 } 148 }
148} 149}
149 150
150std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir, 151std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
151 SaveDataSpaceId space, SaveDataType type, u64 title_id, 152 SaveDataSpaceId space, SaveDataType type, u64 title_id,
152 u128 user_id, u64 save_id) { 153 u128 user_id, u64 save_id) {
153 // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should 154 // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
154 // be interpreted as the title id of the current process. 155 // be interpreted as the title id of the current process.
155 if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { 156 if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
156 if (title_id == 0) { 157 if (title_id == 0) {
157 title_id = system.GetApplicationProcessProgramID(); 158 title_id = program_id;
158 } 159 }
159 } 160 }
160 161
@@ -201,7 +202,7 @@ std::string SaveDataFactory::GetUserGameSaveDataRoot(u128 user_id, bool future)
201SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, 202SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
202 u128 user_id) const { 203 u128 user_id) const {
203 const auto path = 204 const auto path =
204 GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); 205 GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
205 const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); 206 const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
206 207
207 const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName()); 208 const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
@@ -220,7 +221,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
220void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, 221void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
221 SaveDataSize new_value) const { 222 SaveDataSize new_value) const {
222 const auto path = 223 const auto path =
223 GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); 224 GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
224 const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); 225 const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
225 226
226 const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName()); 227 const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index fd4887e99..30d96928e 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -87,10 +87,13 @@ constexpr const char* GetSaveDataSizeFileName() {
87 return ".yuzu_save_size"; 87 return ".yuzu_save_size";
88} 88}
89 89
90using ProgramId = u64;
91
90/// File system interface to the SaveData archive 92/// File system interface to the SaveData archive
91class SaveDataFactory { 93class SaveDataFactory {
92public: 94public:
93 explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); 95 explicit SaveDataFactory(Core::System& system_, ProgramId program_id_,
96 VirtualDir save_directory_);
94 ~SaveDataFactory(); 97 ~SaveDataFactory();
95 98
96 VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; 99 VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
@@ -99,7 +102,7 @@ public:
99 VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; 102 VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
100 103
101 static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); 104 static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space);
102 static std::string GetFullPath(Core::System& system, VirtualDir dir, SaveDataSpaceId space, 105 static std::string GetFullPath(ProgramId program_id, VirtualDir dir, SaveDataSpaceId space,
103 SaveDataType type, u64 title_id, u128 user_id, u64 save_id); 106 SaveDataType type, u64 title_id, u128 user_id, u64 save_id);
104 static std::string GetUserGameSaveDataRoot(u128 user_id, bool future); 107 static std::string GetUserGameSaveDataRoot(u128 user_id, bool future);
105 108
@@ -110,8 +113,9 @@ public:
110 void SetAutoCreate(bool state); 113 void SetAutoCreate(bool state);
111 114
112private: 115private:
113 VirtualDir dir;
114 Core::System& system; 116 Core::System& system;
117 ProgramId program_id;
118 VirtualDir dir;
115 bool auto_create{true}; 119 bool auto_create{true};
116}; 120};
117 121
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9e05bdafa..a768bdc54 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -36,6 +36,7 @@
36#include "core/hle/service/caps/caps_su.h" 36#include "core/hle/service/caps/caps_su.h"
37#include "core/hle/service/caps/caps_types.h" 37#include "core/hle/service/caps/caps_types.h"
38#include "core/hle/service/filesystem/filesystem.h" 38#include "core/hle/service/filesystem/filesystem.h"
39#include "core/hle/service/filesystem/save_data_controller.h"
39#include "core/hle/service/ipc_helpers.h" 40#include "core/hle/service/ipc_helpers.h"
40#include "core/hle/service/ns/ns.h" 41#include "core/hle/service/ns/ns.h"
41#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" 42#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
@@ -2178,7 +2179,7 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
2178 attribute.type = FileSys::SaveDataType::SaveData; 2179 attribute.type = FileSys::SaveDataType::SaveData;
2179 2180
2180 FileSys::VirtualDir save_data{}; 2181 FileSys::VirtualDir save_data{};
2181 const auto res = system.GetFileSystemController().CreateSaveData( 2182 const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
2182 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); 2183 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
2183 2184
2184 IPC::ResponseBuilder rb{ctx, 4}; 2185 IPC::ResponseBuilder rb{ctx, 4};
@@ -2353,7 +2354,7 @@ void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
2353 "new_journal={:016X}", 2354 "new_journal={:016X}",
2354 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); 2355 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
2355 2356
2356 system.GetFileSystemController().WriteSaveDataSize( 2357 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
2357 type, system.GetApplicationProcessProgramID(), user_id, 2358 type, system.GetApplicationProcessProgramID(), user_id,
2358 {new_normal_size, new_journal_size}); 2359 {new_normal_size, new_journal_size});
2359 2360
@@ -2378,7 +2379,7 @@ void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
2378 LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], 2379 LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
2379 user_id[0]); 2380 user_id[0]);
2380 2381
2381 const auto size = system.GetFileSystemController().ReadSaveDataSize( 2382 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
2382 type, system.GetApplicationProcessProgramID(), user_id); 2383 type, system.GetApplicationProcessProgramID(), user_id);
2383 2384
2384 IPC::ResponseBuilder rb{ctx, 6}; 2385 IPC::ResponseBuilder rb{ctx, 6};
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 780f8c74d..ca6d8d607 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -24,15 +24,13 @@
24#include "core/hle/service/filesystem/fsp_ldr.h" 24#include "core/hle/service/filesystem/fsp_ldr.h"
25#include "core/hle/service/filesystem/fsp_pr.h" 25#include "core/hle/service/filesystem/fsp_pr.h"
26#include "core/hle/service/filesystem/fsp_srv.h" 26#include "core/hle/service/filesystem/fsp_srv.h"
27#include "core/hle/service/filesystem/romfs_controller.h"
28#include "core/hle/service/filesystem/save_data_controller.h"
27#include "core/hle/service/server_manager.h" 29#include "core/hle/service/server_manager.h"
28#include "core/loader/loader.h" 30#include "core/loader/loader.h"
29 31
30namespace Service::FileSystem { 32namespace Service::FileSystem {
31 33
32// A default size for normal/journal save data size if application control metadata cannot be found.
33// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
34constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000;
35
36static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, 34static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
37 std::string_view dir_name_) { 35 std::string_view dir_name_) {
38 std::string dir_name(Common::FS::SanitizePath(dir_name_)); 36 std::string dir_name(Common::FS::SanitizePath(dir_name_));
@@ -297,145 +295,65 @@ FileSystemController::FileSystemController(Core::System& system_) : system{syste
297 295
298FileSystemController::~FileSystemController() = default; 296FileSystemController::~FileSystemController() = default;
299 297
300Result FileSystemController::RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) { 298Result FileSystemController::RegisterProcess(
301 romfs_factory = std::move(factory); 299 ProcessId process_id, ProgramId program_id,
302 LOG_DEBUG(Service_FS, "Registered RomFS"); 300 std::shared_ptr<FileSys::RomFSFactory>&& romfs_factory) {
303 return ResultSuccess; 301 std::scoped_lock lk{registration_lock};
304}
305
306Result FileSystemController::RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory) {
307 ASSERT_MSG(save_data_factory == nullptr, "Tried to register a second save data");
308 save_data_factory = std::move(factory);
309 LOG_DEBUG(Service_FS, "Registered save data");
310 return ResultSuccess;
311}
312 302
313Result FileSystemController::RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) { 303 registrations.emplace(process_id, Registration{
314 ASSERT_MSG(sdmc_factory == nullptr, "Tried to register a second SDMC"); 304 .program_id = program_id,
315 sdmc_factory = std::move(factory); 305 .romfs_factory = std::move(romfs_factory),
316 LOG_DEBUG(Service_FS, "Registered SDMC"); 306 .save_data_factory = CreateSaveDataFactory(program_id),
317 return ResultSuccess; 307 });
318}
319 308
320Result FileSystemController::RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) { 309 LOG_DEBUG(Service_FS, "Registered for process {}", process_id);
321 ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS");
322 bis_factory = std::move(factory);
323 LOG_DEBUG(Service_FS, "Registered BIS");
324 return ResultSuccess; 310 return ResultSuccess;
325} 311}
326 312
327void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) { 313Result FileSystemController::OpenProcess(
328 LOG_TRACE(Service_FS, "Setting packed update for romfs"); 314 ProgramId* out_program_id, std::shared_ptr<SaveDataController>* out_save_data_controller,
329 315 std::shared_ptr<RomFsController>* out_romfs_controller, ProcessId process_id) {
330 if (romfs_factory == nullptr) 316 std::scoped_lock lk{registration_lock};
331 return;
332
333 romfs_factory->SetPackedUpdate(std::move(update_raw));
334}
335
336FileSys::VirtualFile FileSystemController::OpenRomFSCurrentProcess() const {
337 LOG_TRACE(Service_FS, "Opening RomFS for current process");
338
339 if (romfs_factory == nullptr) {
340 return nullptr;
341 }
342
343 return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID());
344}
345
346FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id,
347 FileSys::ContentRecordType type) const {
348 LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
349
350 if (romfs_factory == nullptr) {
351 return nullptr;
352 }
353
354 return romfs_factory->OpenPatchedRomFS(title_id, type);
355}
356
357FileSys::VirtualFile FileSystemController::OpenPatchedRomFSWithProgramIndex(
358 u64 title_id, u8 program_index, FileSys::ContentRecordType type) const {
359 LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id,
360 program_index);
361
362 if (romfs_factory == nullptr) {
363 return nullptr;
364 }
365
366 return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
367}
368
369FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
370 FileSys::ContentRecordType type) const {
371 LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
372 title_id, storage_id, type);
373
374 if (romfs_factory == nullptr) {
375 return nullptr;
376 }
377
378 return romfs_factory->Open(title_id, storage_id, type);
379}
380
381std::shared_ptr<FileSys::NCA> FileSystemController::OpenBaseNca(
382 u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const {
383 return romfs_factory->GetEntry(title_id, storage_id, type);
384}
385
386Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
387 FileSys::SaveDataSpaceId space,
388 const FileSys::SaveDataAttribute& save_struct) const {
389 LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
390 save_struct.DebugInfo());
391 317
392 if (save_data_factory == nullptr) { 318 const auto it = registrations.find(process_id);
319 if (it == registrations.end()) {
393 return FileSys::ERROR_ENTITY_NOT_FOUND; 320 return FileSys::ERROR_ENTITY_NOT_FOUND;
394 } 321 }
395 322
396 auto save_data = save_data_factory->Create(space, save_struct); 323 *out_program_id = it->second.program_id;
397 if (save_data == nullptr) { 324 *out_save_data_controller =
398 return FileSys::ERROR_ENTITY_NOT_FOUND; 325 std::make_shared<SaveDataController>(system, it->second.save_data_factory);
399 } 326 *out_romfs_controller =
400 327 std::make_shared<RomFsController>(it->second.romfs_factory, it->second.program_id);
401 *out_save_data = save_data;
402 return ResultSuccess; 328 return ResultSuccess;
403} 329}
404 330
405Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data, 331void FileSystemController::SetPackedUpdate(ProcessId process_id, FileSys::VirtualFile update_raw) {
406 FileSys::SaveDataSpaceId space, 332 LOG_TRACE(Service_FS, "Setting packed update for romfs");
407 const FileSys::SaveDataAttribute& attribute) const {
408 LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space,
409 attribute.DebugInfo());
410
411 if (save_data_factory == nullptr) {
412 return FileSys::ERROR_ENTITY_NOT_FOUND;
413 }
414 333
415 auto save_data = save_data_factory->Open(space, attribute); 334 std::scoped_lock lk{registration_lock};
416 if (save_data == nullptr) { 335 const auto it = registrations.find(process_id);
417 return FileSys::ERROR_ENTITY_NOT_FOUND; 336 if (it == registrations.end()) {
337 return;
418 } 338 }
419 339
420 *out_save_data = save_data; 340 it->second.romfs_factory->SetPackedUpdate(std::move(update_raw));
421 return ResultSuccess;
422} 341}
423 342
424Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, 343std::shared_ptr<SaveDataController> FileSystemController::OpenSaveDataController() {
425 FileSys::SaveDataSpaceId space) const { 344 return std::make_shared<SaveDataController>(system, CreateSaveDataFactory(ProgramId{}));
426 LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); 345}
427
428 if (save_data_factory == nullptr) {
429 return FileSys::ERROR_ENTITY_NOT_FOUND;
430 }
431 346
432 auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space); 347std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory(
433 if (save_data_space == nullptr) { 348 ProgramId program_id) {
434 return FileSys::ERROR_ENTITY_NOT_FOUND; 349 using YuzuPath = Common::FS::YuzuPath;
435 } 350 const auto rw_mode = FileSys::Mode::ReadWrite;
436 351
437 *out_save_data_space = save_data_space; 352 auto vfs = system.GetFilesystem();
438 return ResultSuccess; 353 const auto nand_directory =
354 vfs->OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode);
355 return std::make_shared<FileSys::SaveDataFactory>(system, program_id,
356 std::move(nand_directory));
439} 357}
440 358
441Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const { 359Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {
@@ -540,48 +458,6 @@ u64 FileSystemController::GetTotalSpaceSize(FileSys::StorageId id) const {
540 return 0; 458 return 0;
541} 459}
542 460
543FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataType type,
544 u64 title_id, u128 user_id) const {
545 if (save_data_factory == nullptr) {
546 return {0, 0};
547 }
548
549 const auto value = save_data_factory->ReadSaveDataSize(type, title_id, user_id);
550
551 if (value.normal == 0 && value.journal == 0) {
552 FileSys::SaveDataSize new_size{SUFFICIENT_SAVE_DATA_SIZE, SUFFICIENT_SAVE_DATA_SIZE};
553
554 FileSys::NACP nacp;
555 const auto res = system.GetAppLoader().ReadControlData(nacp);
556
557 if (res != Loader::ResultStatus::Success) {
558 const FileSys::PatchManager pm{system.GetApplicationProcessProgramID(),
559 system.GetFileSystemController(),
560 system.GetContentProvider()};
561 const auto metadata = pm.GetControlMetadata();
562 const auto& nacp_unique = metadata.first;
563
564 if (nacp_unique != nullptr) {
565 new_size = {nacp_unique->GetDefaultNormalSaveSize(),
566 nacp_unique->GetDefaultJournalSaveSize()};
567 }
568 } else {
569 new_size = {nacp.GetDefaultNormalSaveSize(), nacp.GetDefaultJournalSaveSize()};
570 }
571
572 WriteSaveDataSize(type, title_id, user_id, new_size);
573 return new_size;
574 }
575
576 return value;
577}
578
579void FileSystemController::WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
580 FileSys::SaveDataSize new_value) const {
581 if (save_data_factory != nullptr)
582 save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
583}
584
585void FileSystemController::SetGameCard(FileSys::VirtualFile file) { 461void FileSystemController::SetGameCard(FileSys::VirtualFile file) {
586 gamecard = std::make_unique<FileSys::XCI>(file); 462 gamecard = std::make_unique<FileSys::XCI>(file);
587 const auto dir = gamecard->ConcatenatedPseudoDirectory(); 463 const auto dir = gamecard->ConcatenatedPseudoDirectory();
@@ -801,14 +677,9 @@ FileSys::VirtualDir FileSystemController::GetBCATDirectory(u64 title_id) const {
801 return bis_factory->GetBCATDirectory(title_id); 677 return bis_factory->GetBCATDirectory(title_id);
802} 678}
803 679
804void FileSystemController::SetAutoSaveDataCreation(bool enable) {
805 save_data_factory->SetAutoCreate(enable);
806}
807
808void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { 680void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
809 if (overwrite) { 681 if (overwrite) {
810 bis_factory = nullptr; 682 bis_factory = nullptr;
811 save_data_factory = nullptr;
812 sdmc_factory = nullptr; 683 sdmc_factory = nullptr;
813 } 684 }
814 685
@@ -836,11 +707,6 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
836 bis_factory->GetUserNANDContents()); 707 bis_factory->GetUserNANDContents());
837 } 708 }
838 709
839 if (save_data_factory == nullptr) {
840 save_data_factory =
841 std::make_unique<FileSys::SaveDataFactory>(system, std::move(nand_directory));
842 }
843
844 if (sdmc_factory == nullptr) { 710 if (sdmc_factory == nullptr) {
845 sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory), 711 sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory),
846 std::move(sd_load_directory)); 712 std::move(sd_load_directory));
@@ -849,12 +715,19 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
849 } 715 }
850} 716}
851 717
718void FileSystemController::Reset() {
719 std::scoped_lock lk{registration_lock};
720 registrations.clear();
721}
722
852void LoopProcess(Core::System& system) { 723void LoopProcess(Core::System& system) {
853 auto server_manager = std::make_unique<ServerManager>(system); 724 auto server_manager = std::make_unique<ServerManager>(system);
854 725
726 const auto FileSystemProxyFactory = [&] { return std::make_shared<FSP_SRV>(system); };
727
855 server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system)); 728 server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system));
856 server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system)); 729 server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system));
857 server_manager->RegisterNamedService("fsp-srv", std::make_shared<FSP_SRV>(system)); 730 server_manager->RegisterNamedService("fsp-srv", std::move(FileSystemProxyFactory));
858 ServerManager::RunServer(std::move(server_manager)); 731 ServerManager::RunServer(std::move(server_manager));
859} 732}
860 733
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 276d264e1..48f37d289 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -43,6 +43,9 @@ class ServiceManager;
43 43
44namespace FileSystem { 44namespace FileSystem {
45 45
46class RomFsController;
47class SaveDataController;
48
46enum class ContentStorageId : u32 { 49enum class ContentStorageId : u32 {
47 System, 50 System,
48 User, 51 User,
@@ -61,32 +64,24 @@ enum class OpenDirectoryMode : u64 {
61}; 64};
62DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode); 65DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode);
63 66
67using ProcessId = u64;
68using ProgramId = u64;
69
64class FileSystemController { 70class FileSystemController {
65public: 71public:
66 explicit FileSystemController(Core::System& system_); 72 explicit FileSystemController(Core::System& system_);
67 ~FileSystemController(); 73 ~FileSystemController();
68 74
69 Result RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory); 75 Result RegisterProcess(ProcessId process_id, ProgramId program_id,
70 Result RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory); 76 std::shared_ptr<FileSys::RomFSFactory>&& factory);
71 Result RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory); 77 Result OpenProcess(ProgramId* out_program_id,
72 Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); 78 std::shared_ptr<SaveDataController>* out_save_data_controller,
73 79 std::shared_ptr<RomFsController>* out_romfs_controller,
74 void SetPackedUpdate(FileSys::VirtualFile update_raw); 80 ProcessId process_id);
75 FileSys::VirtualFile OpenRomFSCurrentProcess() const; 81 void SetPackedUpdate(ProcessId process_id, FileSys::VirtualFile update_raw);
76 FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const; 82
77 FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, 83 std::shared_ptr<SaveDataController> OpenSaveDataController();
78 FileSys::ContentRecordType type) const; 84
79 FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
80 FileSys::ContentRecordType type) const;
81 std::shared_ptr<FileSys::NCA> OpenBaseNca(u64 title_id, FileSys::StorageId storage_id,
82 FileSys::ContentRecordType type) const;
83
84 Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
85 const FileSys::SaveDataAttribute& save_struct) const;
86 Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
87 const FileSys::SaveDataAttribute& save_struct) const;
88 Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
89 FileSys::SaveDataSpaceId space) const;
90 Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const; 85 Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const;
91 Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition, 86 Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition,
92 FileSys::BisPartitionId id) const; 87 FileSys::BisPartitionId id) const;
@@ -96,11 +91,6 @@ public:
96 u64 GetFreeSpaceSize(FileSys::StorageId id) const; 91 u64 GetFreeSpaceSize(FileSys::StorageId id) const;
97 u64 GetTotalSpaceSize(FileSys::StorageId id) const; 92 u64 GetTotalSpaceSize(FileSys::StorageId id) const;
98 93
99 FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id,
100 u128 user_id) const;
101 void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
102 FileSys::SaveDataSize new_value) const;
103
104 void SetGameCard(FileSys::VirtualFile file); 94 void SetGameCard(FileSys::VirtualFile file);
105 FileSys::XCI* GetGameCard() const; 95 FileSys::XCI* GetGameCard() const;
106 96
@@ -133,15 +123,24 @@ public:
133 123
134 FileSys::VirtualDir GetBCATDirectory(u64 title_id) const; 124 FileSys::VirtualDir GetBCATDirectory(u64 title_id) const;
135 125
136 void SetAutoSaveDataCreation(bool enable);
137
138 // Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function 126 // Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
139 // above is called. 127 // above is called.
140 void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true); 128 void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
141 129
130 void Reset();
131
142private: 132private:
143 std::unique_ptr<FileSys::RomFSFactory> romfs_factory; 133 std::shared_ptr<FileSys::SaveDataFactory> CreateSaveDataFactory(ProgramId program_id);
144 std::unique_ptr<FileSys::SaveDataFactory> save_data_factory; 134
135 struct Registration {
136 ProgramId program_id;
137 std::shared_ptr<FileSys::RomFSFactory> romfs_factory;
138 std::shared_ptr<FileSys::SaveDataFactory> save_data_factory;
139 };
140
141 std::mutex registration_lock;
142 std::map<ProcessId, Registration> registrations;
143
145 std::unique_ptr<FileSys::SDMCFactory> sdmc_factory; 144 std::unique_ptr<FileSys::SDMCFactory> sdmc_factory;
146 std::unique_ptr<FileSys::BISFactory> bis_factory; 145 std::unique_ptr<FileSys::BISFactory> bis_factory;
147 146
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 82ecc1b90..a2397bec4 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -27,6 +27,8 @@
27#include "core/hle/result.h" 27#include "core/hle/result.h"
28#include "core/hle/service/filesystem/filesystem.h" 28#include "core/hle/service/filesystem/filesystem.h"
29#include "core/hle/service/filesystem/fsp_srv.h" 29#include "core/hle/service/filesystem/fsp_srv.h"
30#include "core/hle/service/filesystem/romfs_controller.h"
31#include "core/hle/service/filesystem/save_data_controller.h"
30#include "core/hle/service/hle_ipc.h" 32#include "core/hle/service/hle_ipc.h"
31#include "core/hle/service/ipc_helpers.h" 33#include "core/hle/service/ipc_helpers.h"
32#include "core/reporter.h" 34#include "core/reporter.h"
@@ -577,9 +579,11 @@ private:
577 579
578class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { 580class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
579public: 581public:
580 explicit ISaveDataInfoReader(Core::System& system_, FileSys::SaveDataSpaceId space, 582 explicit ISaveDataInfoReader(Core::System& system_,
581 FileSystemController& fsc_) 583 std::shared_ptr<SaveDataController> save_data_controller_,
582 : ServiceFramework{system_, "ISaveDataInfoReader"}, fsc{fsc_} { 584 FileSys::SaveDataSpaceId space)
585 : ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{
586 save_data_controller_} {
583 static const FunctionInfo functions[] = { 587 static const FunctionInfo functions[] = {
584 {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, 588 {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
585 }; 589 };
@@ -626,7 +630,7 @@ private:
626 630
627 void FindAllSaves(FileSys::SaveDataSpaceId space) { 631 void FindAllSaves(FileSys::SaveDataSpaceId space) {
628 FileSys::VirtualDir save_root{}; 632 FileSys::VirtualDir save_root{};
629 const auto result = fsc.OpenSaveDataSpace(&save_root, space); 633 const auto result = save_data_controller->OpenSaveDataSpace(&save_root, space);
630 634
631 if (result != ResultSuccess || save_root == nullptr) { 635 if (result != ResultSuccess || save_root == nullptr) {
632 LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); 636 LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
@@ -723,7 +727,8 @@ private:
723 }; 727 };
724 static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size."); 728 static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
725 729
726 FileSystemController& fsc; 730 ProcessId process_id = 0;
731 std::shared_ptr<SaveDataController> save_data_controller;
727 std::vector<SaveDataInfo> info; 732 std::vector<SaveDataInfo> info;
728 u64 next_entry_index = 0; 733 u64 next_entry_index = 0;
729}; 734};
@@ -863,21 +868,20 @@ FSP_SRV::FSP_SRV(Core::System& system_)
863 if (Settings::values.enable_fs_access_log) { 868 if (Settings::values.enable_fs_access_log) {
864 access_log_mode = AccessLogMode::SdCard; 869 access_log_mode = AccessLogMode::SdCard;
865 } 870 }
866
867 // This should be true on creation
868 fsc.SetAutoSaveDataCreation(true);
869} 871}
870 872
871FSP_SRV::~FSP_SRV() = default; 873FSP_SRV::~FSP_SRV() = default;
872 874
873void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) { 875void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) {
874 IPC::RequestParser rp{ctx}; 876 current_process_id = ctx.GetPID();
875 current_process_id = rp.Pop<u64>();
876 877
877 LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id); 878 LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id);
878 879
880 const auto res =
881 fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id);
882
879 IPC::ResponseBuilder rb{ctx, 2}; 883 IPC::ResponseBuilder rb{ctx, 2};
880 rb.Push(ResultSuccess); 884 rb.Push(res);
881} 885}
882 886
883void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { 887void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) {
@@ -916,7 +920,8 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) {
916 uid[1], uid[0]); 920 uid[1], uid[0]);
917 921
918 FileSys::VirtualDir save_data_dir{}; 922 FileSys::VirtualDir save_data_dir{};
919 fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct); 923 save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser,
924 save_struct);
920 925
921 IPC::ResponseBuilder rb{ctx, 2}; 926 IPC::ResponseBuilder rb{ctx, 2};
922 rb.Push(ResultSuccess); 927 rb.Push(ResultSuccess);
@@ -931,7 +936,8 @@ void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx)
931 LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo()); 936 LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
932 937
933 FileSys::VirtualDir save_data_dir{}; 938 FileSys::VirtualDir save_data_dir{};
934 fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandSystem, save_struct); 939 save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandSystem,
940 save_struct);
935 941
936 IPC::ResponseBuilder rb{ctx, 2}; 942 IPC::ResponseBuilder rb{ctx, 2};
937 rb.Push(ResultSuccess); 943 rb.Push(ResultSuccess);
@@ -950,7 +956,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
950 LOG_INFO(Service_FS, "called."); 956 LOG_INFO(Service_FS, "called.");
951 957
952 FileSys::VirtualDir dir{}; 958 FileSys::VirtualDir dir{};
953 auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute); 959 auto result =
960 save_data_controller->OpenSaveData(&dir, parameters.space_id, parameters.attribute);
954 if (result != ResultSuccess) { 961 if (result != ResultSuccess) {
955 IPC::ResponseBuilder rb{ctx, 2, 0, 0}; 962 IPC::ResponseBuilder rb{ctx, 2, 0, 0};
956 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); 963 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
@@ -1001,7 +1008,7 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx) {
1001 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1008 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1002 rb.Push(ResultSuccess); 1009 rb.Push(ResultSuccess);
1003 rb.PushIpcInterface<ISaveDataInfoReader>( 1010 rb.PushIpcInterface<ISaveDataInfoReader>(
1004 std::make_shared<ISaveDataInfoReader>(system, space, fsc)); 1011 std::make_shared<ISaveDataInfoReader>(system, save_data_controller, space));
1005} 1012}
1006 1013
1007void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) { 1014void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) {
@@ -1009,8 +1016,8 @@ void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) {
1009 1016
1010 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1017 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1011 rb.Push(ResultSuccess); 1018 rb.Push(ResultSuccess);
1012 rb.PushIpcInterface<ISaveDataInfoReader>(system, FileSys::SaveDataSpaceId::TemporaryStorage, 1019 rb.PushIpcInterface<ISaveDataInfoReader>(system, save_data_controller,
1013 fsc); 1020 FileSys::SaveDataSpaceId::TemporaryStorage);
1014} 1021}
1015 1022
1016void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx) { 1023void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx) {
@@ -1050,7 +1057,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
1050 LOG_DEBUG(Service_FS, "called"); 1057 LOG_DEBUG(Service_FS, "called");
1051 1058
1052 if (!romfs) { 1059 if (!romfs) {
1053 auto current_romfs = fsc.OpenRomFSCurrentProcess(); 1060 auto current_romfs = romfs_controller->OpenRomFSCurrentProcess();
1054 if (!current_romfs) { 1061 if (!current_romfs) {
1055 // TODO (bunnei): Find the right error code to use here 1062 // TODO (bunnei): Find the right error code to use here
1056 LOG_CRITICAL(Service_FS, "no file system interface available!"); 1063 LOG_CRITICAL(Service_FS, "no file system interface available!");
@@ -1078,7 +1085,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
1078 LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}", 1085 LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}",
1079 storage_id, unknown, title_id); 1086 storage_id, unknown, title_id);
1080 1087
1081 auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); 1088 auto data = romfs_controller->OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
1082 1089
1083 if (!data) { 1090 if (!data) {
1084 const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); 1091 const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
@@ -1101,7 +1108,8 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
1101 1108
1102 const FileSys::PatchManager pm{title_id, fsc, content_provider}; 1109 const FileSys::PatchManager pm{title_id, fsc, content_provider};
1103 1110
1104 auto base = fsc.OpenBaseNca(title_id, storage_id, FileSys::ContentRecordType::Data); 1111 auto base =
1112 romfs_controller->OpenBaseNca(title_id, storage_id, FileSys::ContentRecordType::Data);
1105 auto storage = std::make_shared<IStorage>( 1113 auto storage = std::make_shared<IStorage>(
1106 system, pm.PatchRomFS(base.get(), std::move(data), FileSys::ContentRecordType::Data)); 1114 system, pm.PatchRomFS(base.get(), std::move(data), FileSys::ContentRecordType::Data));
1107 1115
@@ -1129,9 +1137,8 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
1129 1137
1130 LOG_DEBUG(Service_FS, "called, program_index={}", program_index); 1138 LOG_DEBUG(Service_FS, "called, program_index={}", program_index);
1131 1139
1132 auto patched_romfs = 1140 auto patched_romfs = romfs_controller->OpenPatchedRomFSWithProgramIndex(
1133 fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, 1141 program_id, program_index, FileSys::ContentRecordType::Program);
1134 FileSys::ContentRecordType::Program);
1135 1142
1136 if (!patched_romfs) { 1143 if (!patched_romfs) {
1137 // TODO: Find the right error code to use here 1144 // TODO: Find the right error code to use here
@@ -1152,7 +1159,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
1152void FSP_SRV::DisableAutoSaveDataCreation(HLERequestContext& ctx) { 1159void FSP_SRV::DisableAutoSaveDataCreation(HLERequestContext& ctx) {
1153 LOG_DEBUG(Service_FS, "called"); 1160 LOG_DEBUG(Service_FS, "called");
1154 1161
1155 fsc.SetAutoSaveDataCreation(false); 1162 save_data_controller->SetAutoCreate(false);
1156 1163
1157 IPC::ResponseBuilder rb{ctx, 2}; 1164 IPC::ResponseBuilder rb{ctx, 2};
1158 rb.Push(ResultSuccess); 1165 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 280bc9867..26980af99 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -17,6 +17,9 @@ class FileSystemBackend;
17 17
18namespace Service::FileSystem { 18namespace Service::FileSystem {
19 19
20class RomFsController;
21class SaveDataController;
22
20enum class AccessLogVersion : u32 { 23enum class AccessLogVersion : u32 {
21 V7_0_0 = 2, 24 V7_0_0 = 2,
22 25
@@ -67,6 +70,9 @@ private:
67 u64 current_process_id = 0; 70 u64 current_process_id = 0;
68 u32 access_log_program_index = 0; 71 u32 access_log_program_index = 0;
69 AccessLogMode access_log_mode = AccessLogMode::None; 72 AccessLogMode access_log_mode = AccessLogMode::None;
73 u64 program_id = 0;
74 std::shared_ptr<SaveDataController> save_data_controller;
75 std::shared_ptr<RomFsController> romfs_controller;
70}; 76};
71 77
72} // namespace Service::FileSystem 78} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/romfs_controller.cpp b/src/core/hle/service/filesystem/romfs_controller.cpp
new file mode 100644
index 000000000..19c9cec72
--- /dev/null
+++ b/src/core/hle/service/filesystem/romfs_controller.cpp
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/filesystem/romfs_controller.h"
5
6namespace Service::FileSystem {
7
8RomFsController::RomFsController(std::shared_ptr<FileSys::RomFSFactory> factory_, u64 program_id_)
9 : factory{std::move(factory_)}, program_id{program_id_} {}
10RomFsController::~RomFsController() = default;
11
12FileSys::VirtualFile RomFsController::OpenRomFSCurrentProcess() {
13 return factory->OpenCurrentProcess(program_id);
14}
15
16FileSys::VirtualFile RomFsController::OpenPatchedRomFS(u64 title_id,
17 FileSys::ContentRecordType type) {
18 return factory->OpenPatchedRomFS(title_id, type);
19}
20
21FileSys::VirtualFile RomFsController::OpenPatchedRomFSWithProgramIndex(
22 u64 title_id, u8 program_index, FileSys::ContentRecordType type) {
23 return factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
24}
25
26FileSys::VirtualFile RomFsController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
27 FileSys::ContentRecordType type) {
28 return factory->Open(title_id, storage_id, type);
29}
30
31std::shared_ptr<FileSys::NCA> RomFsController::OpenBaseNca(u64 title_id,
32 FileSys::StorageId storage_id,
33 FileSys::ContentRecordType type) {
34 return factory->GetEntry(title_id, storage_id, type);
35}
36
37} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/romfs_controller.h b/src/core/hle/service/filesystem/romfs_controller.h
new file mode 100644
index 000000000..9a478f71d
--- /dev/null
+++ b/src/core/hle/service/filesystem/romfs_controller.h
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/file_sys/nca_metadata.h"
7#include "core/file_sys/romfs_factory.h"
8#include "core/file_sys/vfs_types.h"
9
10namespace Service::FileSystem {
11
12class RomFsController {
13public:
14 explicit RomFsController(std::shared_ptr<FileSys::RomFSFactory> factory_, u64 program_id_);
15 ~RomFsController();
16
17 FileSys::VirtualFile OpenRomFSCurrentProcess();
18 FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type);
19 FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
20 FileSys::ContentRecordType type);
21 FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
22 FileSys::ContentRecordType type);
23 std::shared_ptr<FileSys::NCA> OpenBaseNca(u64 title_id, FileSys::StorageId storage_id,
24 FileSys::ContentRecordType type);
25
26private:
27 const std::shared_ptr<FileSys::RomFSFactory> factory;
28 const u64 program_id;
29};
30
31} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/save_data_controller.cpp b/src/core/hle/service/filesystem/save_data_controller.cpp
new file mode 100644
index 000000000..d19b3ea1e
--- /dev/null
+++ b/src/core/hle/service/filesystem/save_data_controller.cpp
@@ -0,0 +1,99 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/file_sys/control_metadata.h"
6#include "core/file_sys/errors.h"
7#include "core/file_sys/patch_manager.h"
8#include "core/hle/service/filesystem/save_data_controller.h"
9#include "core/loader/loader.h"
10
11namespace Service::FileSystem {
12
13namespace {
14
15// A default size for normal/journal save data size if application control metadata cannot be found.
16// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
17constexpr u64 SufficientSaveDataSize = 0xF0000000;
18
19FileSys::SaveDataSize GetDefaultSaveDataSize(Core::System& system, u64 program_id) {
20 const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
21 system.GetContentProvider()};
22 const auto metadata = pm.GetControlMetadata();
23 const auto& nacp = metadata.first;
24
25 if (nacp != nullptr) {
26 return {nacp->GetDefaultNormalSaveSize(), nacp->GetDefaultJournalSaveSize()};
27 }
28
29 return {SufficientSaveDataSize, SufficientSaveDataSize};
30}
31
32} // namespace
33
34SaveDataController::SaveDataController(Core::System& system_,
35 std::shared_ptr<FileSys::SaveDataFactory> factory_)
36 : system{system_}, factory{std::move(factory_)} {}
37SaveDataController::~SaveDataController() = default;
38
39Result SaveDataController::CreateSaveData(FileSys::VirtualDir* out_save_data,
40 FileSys::SaveDataSpaceId space,
41 const FileSys::SaveDataAttribute& attribute) {
42 LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
43 attribute.DebugInfo());
44
45 auto save_data = factory->Create(space, attribute);
46 if (save_data == nullptr) {
47 return FileSys::ERROR_ENTITY_NOT_FOUND;
48 }
49
50 *out_save_data = save_data;
51 return ResultSuccess;
52}
53
54Result SaveDataController::OpenSaveData(FileSys::VirtualDir* out_save_data,
55 FileSys::SaveDataSpaceId space,
56 const FileSys::SaveDataAttribute& attribute) {
57 auto save_data = factory->Open(space, attribute);
58 if (save_data == nullptr) {
59 return FileSys::ERROR_ENTITY_NOT_FOUND;
60 }
61
62 *out_save_data = save_data;
63 return ResultSuccess;
64}
65
66Result SaveDataController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
67 FileSys::SaveDataSpaceId space) {
68 auto save_data_space = factory->GetSaveDataSpaceDirectory(space);
69 if (save_data_space == nullptr) {
70 return FileSys::ERROR_ENTITY_NOT_FOUND;
71 }
72
73 *out_save_data_space = save_data_space;
74 return ResultSuccess;
75}
76
77FileSys::SaveDataSize SaveDataController::ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id,
78 u128 user_id) {
79 const auto value = factory->ReadSaveDataSize(type, title_id, user_id);
80
81 if (value.normal == 0 && value.journal == 0) {
82 const auto size = GetDefaultSaveDataSize(system, title_id);
83 factory->WriteSaveDataSize(type, title_id, user_id, size);
84 return size;
85 }
86
87 return value;
88}
89
90void SaveDataController::WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
91 FileSys::SaveDataSize new_value) {
92 factory->WriteSaveDataSize(type, title_id, user_id, new_value);
93}
94
95void SaveDataController::SetAutoCreate(bool state) {
96 factory->SetAutoCreate(state);
97}
98
99} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/save_data_controller.h b/src/core/hle/service/filesystem/save_data_controller.h
new file mode 100644
index 000000000..863188e4c
--- /dev/null
+++ b/src/core/hle/service/filesystem/save_data_controller.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/file_sys/nca_metadata.h"
7#include "core/file_sys/savedata_factory.h"
8#include "core/file_sys/vfs_types.h"
9
10namespace Service::FileSystem {
11
12class SaveDataController {
13public:
14 explicit SaveDataController(Core::System& system,
15 std::shared_ptr<FileSys::SaveDataFactory> factory_);
16 ~SaveDataController();
17
18 Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
19 const FileSys::SaveDataAttribute& attribute);
20 Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
21 const FileSys::SaveDataAttribute& attribute);
22 Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
23 FileSys::SaveDataSpaceId space);
24
25 FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id);
26 void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
27 FileSys::SaveDataSize new_value);
28 void SetAutoCreate(bool state);
29
30private:
31 Core::System& system;
32 const std::shared_ptr<FileSys::SaveDataFactory> factory;
33};
34
35} // namespace Service::FileSystem
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index c9f8707b7..1e599e78b 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -216,20 +216,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
216 LOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr); 216 LOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr);
217 } 217 }
218 218
219 // Find the RomFS by searching for a ".romfs" file in this directory
220 const auto& files = dir->GetFiles();
221 const auto romfs_iter =
222 std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) {
223 return f->GetName().find(".romfs") != std::string::npos;
224 });
225
226 // Register the RomFS if a ".romfs" file was found
227 if (romfs_iter != files.end() && *romfs_iter != nullptr) {
228 romfs = *romfs_iter;
229 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
230 *this, system.GetContentProvider(), system.GetFileSystemController()));
231 }
232
233 is_loaded = true; 219 is_loaded = true;
234 return {ResultStatus::Success, 220 return {ResultStatus::Success,
235 LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; 221 LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}};
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 814407535..2a32b1276 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -74,8 +74,10 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::S
74 return load_result; 74 return load_result;
75 } 75 }
76 76
77 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( 77 system.GetFileSystemController().RegisterProcess(
78 *this, system.GetContentProvider(), system.GetFileSystemController())); 78 process.GetProcessId(), nca->GetTitleId(),
79 std::make_shared<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
80 system.GetFileSystemController()));
79 81
80 is_loaded = true; 82 is_loaded = true;
81 return load_result; 83 return load_result;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index e74697cda..83371fcbd 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -276,8 +276,10 @@ AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::KProcess& process, Core::S
276 } 276 }
277 277
278 if (romfs != nullptr) { 278 if (romfs != nullptr) {
279 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( 279 system.GetFileSystemController().RegisterProcess(
280 *this, system.GetContentProvider(), system.GetFileSystemController())); 280 process.GetProcessId(), {},
281 std::make_unique<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
282 system.GetFileSystemController()));
281 } 283 }
282 284
283 is_loaded = true; 285 is_loaded = true;
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index f4ab75b77..28116ff3a 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -111,7 +111,8 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
111 111
112 FileSys::VirtualFile update_raw; 112 FileSys::VirtualFile update_raw;
113 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { 113 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
114 system.GetFileSystemController().SetPackedUpdate(std::move(update_raw)); 114 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(),
115 std::move(update_raw));
115 } 116 }
116 117
117 is_loaded = true; 118 is_loaded = true;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 12d72c380..e9abb199a 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -78,7 +78,8 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::KProcess& process, Core::S
78 78
79 FileSys::VirtualFile update_raw; 79 FileSys::VirtualFile update_raw;
80 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { 80 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
81 system.GetFileSystemController().SetPackedUpdate(std::move(update_raw)); 81 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(),
82 std::move(update_raw));
82 } 83 }
83 84
84 is_loaded = true; 85 is_loaded = true;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 4f4c75f5c..29f47bf48 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2292,14 +2292,14 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
2292 ASSERT(user_id); 2292 ASSERT(user_id);
2293 2293
2294 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( 2294 const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
2295 *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, 2295 {}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
2296 FileSys::SaveDataType::SaveData, program_id, user_id->AsU128(), 0); 2296 FileSys::SaveDataType::SaveData, program_id, user_id->AsU128(), 0);
2297 2297
2298 path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); 2298 path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
2299 } else { 2299 } else {
2300 // Device save data 2300 // Device save data
2301 const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath( 2301 const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath(
2302 *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, 2302 {}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
2303 FileSys::SaveDataType::SaveData, program_id, {}, 0); 2303 FileSys::SaveDataType::SaveData, program_id, {}, 0);
2304 2304
2305 path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path); 2305 path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path);
@@ -2662,8 +2662,8 @@ void GMainWindow::RemoveCacheStorage(u64 program_id) {
2662 vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read); 2662 vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read);
2663 2663
2664 const auto cache_storage_path = FileSys::SaveDataFactory::GetFullPath( 2664 const auto cache_storage_path = FileSys::SaveDataFactory::GetFullPath(
2665 *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, 2665 {}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::CacheStorage,
2666 FileSys::SaveDataType::CacheStorage, 0 /* program_id */, {}, 0); 2666 0 /* program_id */, {}, 0);
2667 2667
2668 const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path); 2668 const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path);
2669 2669