summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Viktor Szépe2024-01-16 00:09:00 +0000
committerGravatar Viktor Szépe2024-01-16 00:09:00 +0000
commit90ab89a0b0174f8df559b79dc06a03479d959f93 (patch)
tree3d11a790e44945e309f0e68f5332b33b42e72bbb /src/core/hle
parentFix typos in arrays.xml (diff)
parentMerge pull request #12681 from t895/stick-toggles (diff)
downloadyuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.gz
yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.xz
yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.zip
Merge remote-tracking branch 'origin/master' into typos3
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.cpp4
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h4
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp34
-rw-r--r--src/core/hle/kernel/k_page_table_base.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp10
-rw-r--r--src/core/hle/kernel/kernel.cpp31
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp8
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp19
-rw-r--r--src/core/hle/service/acc/profile_manager.h1
-rw-r--r--src/core/hle/service/am/am.cpp7
-rw-r--r--src/core/hle/service/audio/audin_u.cpp36
-rw-r--r--src/core/hle/service/audio/audout_u.cpp26
-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/hle/service/glue/arp.cpp7
-rw-r--r--src/core/hle/service/hid/hid.cpp10
-rw-r--r--src/core/hle/service/hid/hid_server.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp3
-rw-r--r--src/core/hle/service/pm/pm.cpp85
-rw-r--r--src/core/hle/service/server_manager.cpp9
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp13
-rw-r--r--src/core/hle/service/vi/display/vi_display.h12
-rw-r--r--src/core/hle/service/vi/vi.cpp59
-rw-r--r--src/core/hle/service/vi/vi.h2
31 files changed, 560 insertions, 378 deletions
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp
index 58a1e7216..f08a6e448 100644
--- a/src/core/hle/kernel/k_memory_block_manager.cpp
+++ b/src/core/hle/kernel/k_memory_block_manager.cpp
@@ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd,
28} 28}
29 29
30void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, 30void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager,
31 HostUnmapCallback&& host_unmap_callback) { 31 BlockCallback&& block_callback) {
32 // Erase every block until we have none left. 32 // Erase every block until we have none left.
33 auto it = m_memory_block_tree.begin(); 33 auto it = m_memory_block_tree.begin();
34 while (it != m_memory_block_tree.end()) { 34 while (it != m_memory_block_tree.end()) {
35 KMemoryBlock* block = std::addressof(*it); 35 KMemoryBlock* block = std::addressof(*it);
36 it = m_memory_block_tree.erase(it); 36 it = m_memory_block_tree.erase(it);
37 block_callback(block->GetAddress(), block->GetSize());
37 slab_manager->Free(block); 38 slab_manager->Free(block);
38 host_unmap_callback(block->GetAddress(), block->GetSize());
39 } 39 }
40 40
41 ASSERT(m_memory_block_tree.empty()); 41 ASSERT(m_memory_block_tree.empty());
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h
index cb7b6f430..377628504 100644
--- a/src/core/hle/kernel/k_memory_block_manager.h
+++ b/src/core/hle/kernel/k_memory_block_manager.h
@@ -85,11 +85,11 @@ public:
85public: 85public:
86 KMemoryBlockManager(); 86 KMemoryBlockManager();
87 87
88 using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>; 88 using BlockCallback = std::function<void(Common::ProcessAddress, u64)>;
89 89
90 Result Initialize(KProcessAddress st, KProcessAddress nd, 90 Result Initialize(KProcessAddress st, KProcessAddress nd,
91 KMemoryBlockSlabManager* slab_manager); 91 KMemoryBlockSlabManager* slab_manager);
92 void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); 92 void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback);
93 93
94 iterator end() { 94 iterator end() {
95 return m_memory_block_tree.end(); 95 return m_memory_block_tree.end();
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 73fbda331..3f0a39d33 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -431,15 +431,43 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
431 m_memory_block_slab_manager)); 431 m_memory_block_slab_manager));
432} 432}
433 433
434Result KPageTableBase::FinalizeProcess() {
435 // Only process tables should be finalized.
436 ASSERT(!this->IsKernel());
437
438 // NOTE: Here Nintendo calls an unknown OnFinalize function.
439 // this->OnFinalize();
440
441 // NOTE: Here Nintendo calls a second unknown OnFinalize function.
442 // this->OnFinalize2();
443
444 // NOTE: Here Nintendo does a page table walk to discover heap pages to free.
445 // We will use the block manager finalization below to free them.
446
447 R_SUCCEED();
448}
449
434void KPageTableBase::Finalize() { 450void KPageTableBase::Finalize() {
435 auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { 451 this->FinalizeProcess();
436 if (Settings::IsFastmemEnabled()) { 452
453 auto BlockCallback = [&](KProcessAddress addr, u64 size) {
454 if (m_impl->fastmem_arena) {
437 m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); 455 m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
438 } 456 }
457
458 // Get physical pages.
459 KPageGroup pg(m_kernel, m_block_info_manager);
460 this->MakePageGroup(pg, addr, size / PageSize);
461
462 // Free the pages.
463 pg.CloseAndReset();
439 }; 464 };
440 465
441 // Finalize memory blocks. 466 // Finalize memory blocks.
442 m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback)); 467 {
468 KScopedLightLock lk(m_general_lock);
469 m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback));
470 }
443 471
444 // Free any unsafe mapped memory. 472 // Free any unsafe mapped memory.
445 if (m_mapped_unsafe_physical_memory) { 473 if (m_mapped_unsafe_physical_memory) {
diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h
index 077cafc96..748419f86 100644
--- a/src/core/hle/kernel/k_page_table_base.h
+++ b/src/core/hle/kernel/k_page_table_base.h
@@ -241,6 +241,7 @@ public:
241 KResourceLimit* resource_limit, Core::Memory::Memory& memory, 241 KResourceLimit* resource_limit, Core::Memory::Memory& memory,
242 KProcessAddress aslr_space_start); 242 KProcessAddress aslr_space_start);
243 243
244 Result FinalizeProcess();
244 void Finalize(); 245 void Finalize();
245 246
246 bool IsKernel() const { 247 bool IsKernel() const {
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 068e71dff..53735a225 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -171,6 +171,12 @@ void KProcess::Finalize() {
171 m_resource_limit->Close(); 171 m_resource_limit->Close();
172 } 172 }
173 173
174 // Clear expensive resources, as the destructor is not called for guest objects.
175 for (auto& interface : m_arm_interfaces) {
176 interface.reset();
177 }
178 m_exclusive_monitor.reset();
179
174 // Perform inherited finalization. 180 // Perform inherited finalization.
175 KSynchronizationObject::Finalize(); 181 KSynchronizationObject::Finalize();
176} 182}
@@ -1233,10 +1239,10 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
1233 ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); 1239 ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
1234 1240
1235#ifdef HAS_NCE 1241#ifdef HAS_NCE
1236 if (this->IsApplication() && Settings::IsNceEnabled()) { 1242 const auto& patch = code_set.PatchSegment();
1243 if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) {
1237 auto& buffer = m_kernel.System().DeviceMemory().buffer; 1244 auto& buffer = m_kernel.System().DeviceMemory().buffer;
1238 const auto& code = code_set.CodeSegment(); 1245 const auto& code = code_set.CodeSegment();
1239 const auto& patch = code_set.PatchSegment();
1240 buffer.Protect(GetInteger(base_addr + code.addr), code.size, 1246 buffer.Protect(GetInteger(base_addr + code.addr), code.size,
1241 Common::MemoryPermission::Read | Common::MemoryPermission::Execute); 1247 Common::MemoryPermission::Read | Common::MemoryPermission::Execute);
1242 buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, 1248 buffer.Protect(GetInteger(base_addr + patch.addr), patch.size,
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1030f0c12..f3683cdcc 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -112,7 +112,14 @@ struct KernelCore::Impl {
112 old_process->Close(); 112 old_process->Close();
113 } 113 }
114 114
115 process_list.clear(); 115 {
116 std::scoped_lock lk{process_list_lock};
117 for (auto* const process : process_list) {
118 process->Terminate();
119 process->Close();
120 }
121 process_list.clear();
122 }
116 123
117 next_object_id = 0; 124 next_object_id = 0;
118 next_kernel_process_id = KProcess::InitialProcessIdMin; 125 next_kernel_process_id = KProcess::InitialProcessIdMin;
@@ -770,6 +777,7 @@ struct KernelCore::Impl {
770 std::atomic<u64> next_thread_id{1}; 777 std::atomic<u64> next_thread_id{1};
771 778
772 // Lists all processes that exist in the current session. 779 // Lists all processes that exist in the current session.
780 std::mutex process_list_lock;
773 std::vector<KProcess*> process_list; 781 std::vector<KProcess*> process_list;
774 std::atomic<KProcess*> application_process{}; 782 std::atomic<KProcess*> application_process{};
775 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 783 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
@@ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
869} 877}
870 878
871void KernelCore::AppendNewProcess(KProcess* process) { 879void KernelCore::AppendNewProcess(KProcess* process) {
880 process->Open();
881
882 std::scoped_lock lk{impl->process_list_lock};
872 impl->process_list.push_back(process); 883 impl->process_list.push_back(process);
873} 884}
874 885
886void KernelCore::RemoveProcess(KProcess* process) {
887 std::scoped_lock lk{impl->process_list_lock};
888 if (std::erase(impl->process_list, process)) {
889 process->Close();
890 }
891}
892
875void KernelCore::MakeApplicationProcess(KProcess* process) { 893void KernelCore::MakeApplicationProcess(KProcess* process) {
876 impl->MakeApplicationProcess(process); 894 impl->MakeApplicationProcess(process);
877} 895}
@@ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const {
884 return impl->application_process; 902 return impl->application_process;
885} 903}
886 904
887const std::vector<KProcess*>& KernelCore::GetProcessList() const { 905std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
888 return impl->process_list; 906 std::list<KScopedAutoObject<KProcess>> processes;
907 std::scoped_lock lk{impl->process_list_lock};
908
909 for (auto* const process : impl->process_list) {
910 processes.emplace_back(process);
911 }
912
913 return processes;
889} 914}
890 915
891Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { 916Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 5d4102145..8ea5bed1c 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -5,6 +5,7 @@
5 5
6#include <array> 6#include <array>
7#include <functional> 7#include <functional>
8#include <list>
8#include <memory> 9#include <memory>
9#include <string> 10#include <string>
10#include <unordered_map> 11#include <unordered_map>
@@ -116,8 +117,9 @@ public:
116 /// Retrieves a shared pointer to the system resource limit instance. 117 /// Retrieves a shared pointer to the system resource limit instance.
117 KResourceLimit* GetSystemResourceLimit(); 118 KResourceLimit* GetSystemResourceLimit();
118 119
119 /// Adds the given shared pointer to an internal list of active processes. 120 /// Adds/removes the given pointer to an internal list of active processes.
120 void AppendNewProcess(KProcess* process); 121 void AppendNewProcess(KProcess* process);
122 void RemoveProcess(KProcess* process);
121 123
122 /// Makes the given process the new application process. 124 /// Makes the given process the new application process.
123 void MakeApplicationProcess(KProcess* process); 125 void MakeApplicationProcess(KProcess* process);
@@ -129,7 +131,7 @@ public:
129 const KProcess* ApplicationProcess() const; 131 const KProcess* ApplicationProcess() const;
130 132
131 /// Retrieves the list of processes. 133 /// Retrieves the list of processes.
132 const std::vector<KProcess*>& GetProcessList() const; 134 std::list<KScopedAutoObject<KProcess>> GetProcessList();
133 135
134 /// Gets the sole instance of the global scheduler 136 /// Gets the sole instance of the global scheduler
135 Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); 137 Kernel::GlobalSchedulerContext& GlobalSchedulerContext();
diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp
index caa8bee9a..5c3e8829f 100644
--- a/src/core/hle/kernel/svc/svc_process.cpp
+++ b/src/core/hle/kernel/svc/svc_process.cpp
@@ -74,13 +74,15 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
74 } 74 }
75 75
76 auto& memory = GetCurrentMemory(kernel); 76 auto& memory = GetCurrentMemory(kernel);
77 const auto& process_list = kernel.GetProcessList(); 77 auto process_list = kernel.GetProcessList();
78 auto it = process_list.begin();
79
78 const auto num_processes = process_list.size(); 80 const auto num_processes = process_list.size();
79 const auto copy_amount = 81 const auto copy_amount =
80 std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); 82 std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
81 83
82 for (std::size_t i = 0; i < copy_amount; ++i) { 84 for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) {
83 memory.Write64(out_process_ids, process_list[i]->GetProcessId()); 85 memory.Write64(out_process_ids, (*it)->GetProcessId());
84 out_process_ids += sizeof(u64); 86 out_process_ids += sizeof(u64);
85 } 87 }
86 88
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 5542d6cbc..683f44e27 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -61,9 +61,7 @@ ProfileManager::ProfileManager() {
61 OpenUser(*GetUser(current)); 61 OpenUser(*GetUser(current));
62} 62}
63 63
64ProfileManager::~ProfileManager() { 64ProfileManager::~ProfileManager() = default;
65 WriteUserSaveFile();
66}
67 65
68/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the 66/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the
69/// internal management of the users profiles 67/// internal management of the users profiles
@@ -113,6 +111,8 @@ Result ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& username)
113 return ERROR_USER_ALREADY_EXISTS; 111 return ERROR_USER_ALREADY_EXISTS;
114 } 112 }
115 113
114 is_save_needed = true;
115
116 return AddUser({ 116 return AddUser({
117 .user_uuid = uuid, 117 .user_uuid = uuid,
118 .username = username, 118 .username = username,
@@ -326,6 +326,9 @@ bool ProfileManager::RemoveUser(UUID uuid) {
326 profiles[*index] = ProfileInfo{}; 326 profiles[*index] = ProfileInfo{};
327 std::stable_partition(profiles.begin(), profiles.end(), 327 std::stable_partition(profiles.begin(), profiles.end(),
328 [](const ProfileInfo& profile) { return profile.user_uuid.IsValid(); }); 328 [](const ProfileInfo& profile) { return profile.user_uuid.IsValid(); });
329
330 is_save_needed = true;
331
329 return true; 332 return true;
330} 333}
331 334
@@ -340,6 +343,8 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
340 profile.username = profile_new.username; 343 profile.username = profile_new.username;
341 profile.creation_time = profile_new.timestamp; 344 profile.creation_time = profile_new.timestamp;
342 345
346 is_save_needed = true;
347
343 return true; 348 return true;
344} 349}
345 350
@@ -348,6 +353,7 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase&
348 const auto index = GetUserIndex(uuid); 353 const auto index = GetUserIndex(uuid);
349 if (index.has_value() && SetProfileBase(uuid, profile_new)) { 354 if (index.has_value() && SetProfileBase(uuid, profile_new)) {
350 profiles[*index].data = data_new; 355 profiles[*index].data = data_new;
356 is_save_needed = true;
351 return true; 357 return true;
352 } 358 }
353 359
@@ -391,6 +397,10 @@ void ProfileManager::ParseUserSaveFile() {
391} 397}
392 398
393void ProfileManager::WriteUserSaveFile() { 399void ProfileManager::WriteUserSaveFile() {
400 if (!is_save_needed) {
401 return;
402 }
403
394 ProfileDataRaw raw{}; 404 ProfileDataRaw raw{};
395 405
396 for (std::size_t i = 0; i < MAX_USERS; ++i) { 406 for (std::size_t i = 0; i < MAX_USERS; ++i) {
@@ -423,7 +433,10 @@ void ProfileManager::WriteUserSaveFile() {
423 if (!save.IsOpen() || !save.SetSize(sizeof(ProfileDataRaw)) || !save.WriteObject(raw)) { 433 if (!save.IsOpen() || !save.SetSize(sizeof(ProfileDataRaw)) || !save.WriteObject(raw)) {
424 LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data " 434 LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data "
425 "made in current session will be saved."); 435 "made in current session will be saved.");
436 return;
426 } 437 }
438
439 is_save_needed = false;
427} 440}
428 441
429}; // namespace Service::Account 442}; // namespace Service::Account
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 900e32200..e21863e64 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -103,6 +103,7 @@ private:
103 std::optional<std::size_t> AddToProfiles(const ProfileInfo& profile); 103 std::optional<std::size_t> AddToProfiles(const ProfileInfo& profile);
104 bool RemoveProfileAtIndex(std::size_t index); 104 bool RemoveProfileAtIndex(std::size_t index);
105 105
106 bool is_save_needed{};
106 std::array<ProfileInfo, MAX_USERS> profiles{}; 107 std::array<ProfileInfo, MAX_USERS> profiles{};
107 std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{}; 108 std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{};
108 std::size_t user_count{}; 109 std::size_t user_count{};
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/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 56fee4591..de2aa6906 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -18,11 +18,11 @@ using namespace AudioCore::AudioIn;
18class IAudioIn final : public ServiceFramework<IAudioIn> { 18class IAudioIn final : public ServiceFramework<IAudioIn> {
19public: 19public:
20 explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, 20 explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
21 const std::string& device_name, const AudioInParameter& in_params, u32 handle, 21 const std::string& device_name, const AudioInParameter& in_params,
22 u64 applet_resource_user_id) 22 Kernel::KProcess* handle, u64 applet_resource_user_id)
23 : ServiceFramework{system_, "IAudioIn"}, 23 : ServiceFramework{system_, "IAudioIn"},
24 service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, 24 service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
25 impl{std::make_shared<In>(system_, manager, event, session_id)} { 25 process{handle}, impl{std::make_shared<In>(system_, manager, event, session_id)} {
26 // clang-format off 26 // clang-format off
27 static const FunctionInfo functions[] = { 27 static const FunctionInfo functions[] = {
28 {0, &IAudioIn::GetAudioInState, "GetAudioInState"}, 28 {0, &IAudioIn::GetAudioInState, "GetAudioInState"},
@@ -45,6 +45,8 @@ public:
45 45
46 RegisterHandlers(functions); 46 RegisterHandlers(functions);
47 47
48 process->Open();
49
48 if (impl->GetSystem() 50 if (impl->GetSystem()
49 .Initialize(device_name, in_params, handle, applet_resource_user_id) 51 .Initialize(device_name, in_params, handle, applet_resource_user_id)
50 .IsError()) { 52 .IsError()) {
@@ -55,6 +57,7 @@ public:
55 ~IAudioIn() override { 57 ~IAudioIn() override {
56 impl->Free(); 58 impl->Free();
57 service_context.CloseEvent(event); 59 service_context.CloseEvent(event);
60 process->Close();
58 } 61 }
59 62
60 [[nodiscard]] std::shared_ptr<In> GetImpl() { 63 [[nodiscard]] std::shared_ptr<In> GetImpl() {
@@ -196,6 +199,7 @@ private:
196 199
197 KernelHelpers::ServiceContext service_context; 200 KernelHelpers::ServiceContext service_context;
198 Kernel::KEvent* event; 201 Kernel::KEvent* event;
202 Kernel::KProcess* process;
199 std::shared_ptr<AudioCore::AudioIn::In> impl; 203 std::shared_ptr<AudioCore::AudioIn::In> impl;
200 Common::ScratchBuffer<u64> released_buffer; 204 Common::ScratchBuffer<u64> released_buffer;
201}; 205};
@@ -267,6 +271,14 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
267 auto device_name = Common::StringFromBuffer(device_name_data); 271 auto device_name = Common::StringFromBuffer(device_name_data);
268 auto handle{ctx.GetCopyHandle(0)}; 272 auto handle{ctx.GetCopyHandle(0)};
269 273
274 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
275 if (process.IsNull()) {
276 LOG_ERROR(Service_Audio, "Failed to get process handle");
277 IPC::ResponseBuilder rb{ctx, 2};
278 rb.Push(ResultUnknown);
279 return;
280 }
281
270 std::scoped_lock l{impl->mutex}; 282 std::scoped_lock l{impl->mutex};
271 auto link{impl->LinkToManager()}; 283 auto link{impl->LinkToManager()};
272 if (link.IsError()) { 284 if (link.IsError()) {
@@ -287,8 +299,9 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
287 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, 299 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
288 impl->num_free_sessions); 300 impl->num_free_sessions);
289 301
290 auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, 302 auto audio_in =
291 in_params, handle, applet_resource_user_id); 303 std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
304 process.GetPointerUnsafe(), applet_resource_user_id);
292 impl->sessions[new_session_id] = audio_in->GetImpl(); 305 impl->sessions[new_session_id] = audio_in->GetImpl();
293 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; 306 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
294 307
@@ -318,6 +331,14 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
318 auto device_name = Common::StringFromBuffer(device_name_data); 331 auto device_name = Common::StringFromBuffer(device_name_data);
319 auto handle{ctx.GetCopyHandle(0)}; 332 auto handle{ctx.GetCopyHandle(0)};
320 333
334 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
335 if (process.IsNull()) {
336 LOG_ERROR(Service_Audio, "Failed to get process handle");
337 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(ResultUnknown);
339 return;
340 }
341
321 std::scoped_lock l{impl->mutex}; 342 std::scoped_lock l{impl->mutex};
322 auto link{impl->LinkToManager()}; 343 auto link{impl->LinkToManager()};
323 if (link.IsError()) { 344 if (link.IsError()) {
@@ -338,8 +359,9 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
338 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, 359 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
339 impl->num_free_sessions); 360 impl->num_free_sessions);
340 361
341 auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, 362 auto audio_in =
342 in_params, handle, applet_resource_user_id); 363 std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
364 process.GetPointerUnsafe(), applet_resource_user_id);
343 impl->sessions[new_session_id] = audio_in->GetImpl(); 365 impl->sessions[new_session_id] = audio_in->GetImpl();
344 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; 366 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
345 367
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index ca683d72c..8cc7b69f4 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -26,9 +26,10 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
26public: 26public:
27 explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, 27 explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
28 size_t session_id, const std::string& device_name, 28 size_t session_id, const std::string& device_name,
29 const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) 29 const AudioOutParameter& in_params, Kernel::KProcess* handle,
30 u64 applet_resource_user_id)
30 : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, 31 : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
31 event{service_context.CreateEvent("AudioOutEvent")}, 32 event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
32 impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { 33 impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
33 34
34 // clang-format off 35 // clang-format off
@@ -50,11 +51,14 @@ public:
50 }; 51 };
51 // clang-format on 52 // clang-format on
52 RegisterHandlers(functions); 53 RegisterHandlers(functions);
54
55 process->Open();
53 } 56 }
54 57
55 ~IAudioOut() override { 58 ~IAudioOut() override {
56 impl->Free(); 59 impl->Free();
57 service_context.CloseEvent(event); 60 service_context.CloseEvent(event);
61 process->Close();
58 } 62 }
59 63
60 [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() { 64 [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
@@ -206,6 +210,7 @@ private:
206 210
207 KernelHelpers::ServiceContext service_context; 211 KernelHelpers::ServiceContext service_context;
208 Kernel::KEvent* event; 212 Kernel::KEvent* event;
213 Kernel::KProcess* process;
209 std::shared_ptr<AudioCore::AudioOut::Out> impl; 214 std::shared_ptr<AudioCore::AudioOut::Out> impl;
210 Common::ScratchBuffer<u64> released_buffer; 215 Common::ScratchBuffer<u64> released_buffer;
211}; 216};
@@ -257,6 +262,14 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
257 auto device_name = Common::StringFromBuffer(device_name_data); 262 auto device_name = Common::StringFromBuffer(device_name_data);
258 auto handle{ctx.GetCopyHandle(0)}; 263 auto handle{ctx.GetCopyHandle(0)};
259 264
265 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
266 if (process.IsNull()) {
267 LOG_ERROR(Service_Audio, "Failed to get process handle");
268 IPC::ResponseBuilder rb{ctx, 2};
269 rb.Push(ResultUnknown);
270 return;
271 }
272
260 auto link{impl->LinkToManager()}; 273 auto link{impl->LinkToManager()};
261 if (link.IsError()) { 274 if (link.IsError()) {
262 LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager"); 275 LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager");
@@ -276,10 +289,11 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
276 LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, 289 LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
277 impl->num_free_sessions); 290 impl->num_free_sessions);
278 291
279 auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, 292 auto audio_out =
280 in_params, handle, applet_resource_user_id); 293 std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params,
281 result = audio_out->GetImpl()->GetSystem().Initialize(device_name, in_params, handle, 294 process.GetPointerUnsafe(), applet_resource_user_id);
282 applet_resource_user_id); 295 result = audio_out->GetImpl()->GetSystem().Initialize(
296 device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id);
283 if (result.IsError()) { 297 if (result.IsError()) {
284 LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); 298 LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!");
285 IPC::ResponseBuilder rb{ctx, 2}; 299 IPC::ResponseBuilder rb{ctx, 2};
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/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index 6f1151b03..1254b6d49 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -15,9 +15,10 @@
15namespace Service::Glue { 15namespace Service::Glue {
16 16
17namespace { 17namespace {
18std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { 18std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) {
19 const auto& list = system.Kernel().GetProcessList(); 19 auto list = system.Kernel().GetProcessList();
20 const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { 20
21 const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) {
21 return process->GetProcessId() == process_id; 22 return process->GetProcessId() == process_id;
22 }); 23 });
23 24
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index fc03a0a5f..4ce0a9834 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -22,12 +22,10 @@ void LoopProcess(Core::System& system) {
22 std::shared_ptr<HidFirmwareSettings> firmware_settings = 22 std::shared_ptr<HidFirmwareSettings> firmware_settings =
23 std::make_shared<HidFirmwareSettings>(); 23 std::make_shared<HidFirmwareSettings>();
24 24
25 // TODO: Remove this hack until this service is emulated properly. 25 // TODO: Remove this hack when am is emulated properly.
26 const auto process_list = system.Kernel().GetProcessList(); 26 resource_manager->Initialize();
27 if (!process_list.empty()) { 27 resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(),
28 resource_manager->Initialize(); 28 true);
29 resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
30 }
31 29
32 server_manager->RegisterNamedService( 30 server_manager->RegisterNamedService(
33 "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); 31 "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
index 74898888a..1951da33b 100644
--- a/src/core/hle/service/hid/hid_server.cpp
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -1498,7 +1498,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1498 bool check_device_index = false; 1498 bool check_device_index = false;
1499 1499
1500 switch (vibration_device_handle.npad_type) { 1500 switch (vibration_device_handle.npad_type) {
1501 case Core::HID::NpadStyleIndex::ProController: 1501 case Core::HID::NpadStyleIndex::Fullkey:
1502 case Core::HID::NpadStyleIndex::Handheld: 1502 case Core::HID::NpadStyleIndex::Handheld:
1503 case Core::HID::NpadStyleIndex::JoyconDual: 1503 case Core::HID::NpadStyleIndex::JoyconDual:
1504 case Core::HID::NpadStyleIndex::JoyconLeft: 1504 case Core::HID::NpadStyleIndex::JoyconLeft:
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index aa8aaa2d9..0469110e8 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -223,7 +223,8 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
223 return VI::ResultNotFound; 223 return VI::ResultNotFound;
224 } 224 }
225 225
226 return display->GetVSyncEvent(out_vsync_event); 226 *out_vsync_event = display->GetVSyncEvent();
227 return ResultSuccess;
227} 228}
228 229
229VI::Display* Nvnflinger::FindDisplay(u64 display_id) { 230VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index d92499f05..b52468e41 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -22,27 +22,26 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1};
22 22
23constexpr u64 NO_PROCESS_FOUND_PID{0}; 23constexpr u64 NO_PROCESS_FOUND_PID{0};
24 24
25std::optional<Kernel::KProcess*> SearchProcessList( 25using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>;
26 const std::vector<Kernel::KProcess*>& process_list, 26
27 std::function<bool(Kernel::KProcess*)> predicate) { 27template <typename F>
28Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list,
29 F&& predicate) {
28 const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); 30 const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate);
29 31
30 if (iter == process_list.end()) { 32 if (iter == process_list.end()) {
31 return std::nullopt; 33 return nullptr;
32 } 34 }
33 35
34 return *iter; 36 return iter->GetPointerUnsafe();
35} 37}
36 38
37void GetApplicationPidGeneric(HLERequestContext& ctx, 39void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) {
38 const std::vector<Kernel::KProcess*>& process_list) { 40 auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); });
39 const auto process = SearchProcessList(process_list, [](const auto& proc) {
40 return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin;
41 });
42 41
43 IPC::ResponseBuilder rb{ctx, 4}; 42 IPC::ResponseBuilder rb{ctx, 4};
44 rb.Push(ResultSuccess); 43 rb.Push(ResultSuccess);
45 rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID); 44 rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId());
46} 45}
47 46
48} // Anonymous namespace 47} // Anonymous namespace
@@ -80,8 +79,7 @@ private:
80 79
81class DebugMonitor final : public ServiceFramework<DebugMonitor> { 80class DebugMonitor final : public ServiceFramework<DebugMonitor> {
82public: 81public:
83 explicit DebugMonitor(Core::System& system_) 82 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} {
84 : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} {
85 // clang-format off 83 // clang-format off
86 static const FunctionInfo functions[] = { 84 static const FunctionInfo functions[] = {
87 {0, nullptr, "GetJitDebugProcessIdList"}, 85 {0, nullptr, "GetJitDebugProcessIdList"},
@@ -106,12 +104,11 @@ private:
106 104
107 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); 105 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
108 106
109 const auto process = 107 auto list = kernel.GetProcessList();
110 SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { 108 auto process = SearchProcessList(
111 return proc->GetProgramId() == program_id; 109 list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
112 });
113 110
114 if (!process.has_value()) { 111 if (process.IsNull()) {
115 IPC::ResponseBuilder rb{ctx, 2}; 112 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ResultProcessNotFound); 113 rb.Push(ResultProcessNotFound);
117 return; 114 return;
@@ -119,12 +116,13 @@ private:
119 116
120 IPC::ResponseBuilder rb{ctx, 4}; 117 IPC::ResponseBuilder rb{ctx, 4};
121 rb.Push(ResultSuccess); 118 rb.Push(ResultSuccess);
122 rb.Push((*process)->GetProcessId()); 119 rb.Push(process->GetProcessId());
123 } 120 }
124 121
125 void GetApplicationProcessId(HLERequestContext& ctx) { 122 void GetApplicationProcessId(HLERequestContext& ctx) {
126 LOG_DEBUG(Service_PM, "called"); 123 LOG_DEBUG(Service_PM, "called");
127 GetApplicationPidGeneric(ctx, kernel.GetProcessList()); 124 auto list = kernel.GetProcessList();
125 GetApplicationPidGeneric(ctx, list);
128 } 126 }
129 127
130 void AtmosphereGetProcessInfo(HLERequestContext& ctx) { 128 void AtmosphereGetProcessInfo(HLERequestContext& ctx) {
@@ -135,11 +133,10 @@ private:
135 133
136 LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); 134 LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
137 135
138 const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { 136 auto list = kernel.GetProcessList();
139 return proc->GetProcessId() == pid; 137 auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; });
140 });
141 138
142 if (!process.has_value()) { 139 if (process.IsNull()) {
143 IPC::ResponseBuilder rb{ctx, 2}; 140 IPC::ResponseBuilder rb{ctx, 2};
144 rb.Push(ResultProcessNotFound); 141 rb.Push(ResultProcessNotFound);
145 return; 142 return;
@@ -159,7 +156,7 @@ private:
159 156
160 OverrideStatus override_status{}; 157 OverrideStatus override_status{};
161 ProgramLocation program_location{ 158 ProgramLocation program_location{
162 .program_id = (*process)->GetProgramId(), 159 .program_id = process->GetProgramId(),
163 .storage_id = 0, 160 .storage_id = 0,
164 }; 161 };
165 162
@@ -169,14 +166,11 @@ private:
169 rb.PushRaw(program_location); 166 rb.PushRaw(program_location);
170 rb.PushRaw(override_status); 167 rb.PushRaw(override_status);
171 } 168 }
172
173 const Kernel::KernelCore& kernel;
174}; 169};
175 170
176class Info final : public ServiceFramework<Info> { 171class Info final : public ServiceFramework<Info> {
177public: 172public:
178 explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) 173 explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} {
179 : ServiceFramework{system_, "pm:info"}, process_list{process_list_} {
180 static const FunctionInfo functions[] = { 174 static const FunctionInfo functions[] = {
181 {0, &Info::GetProgramId, "GetProgramId"}, 175 {0, &Info::GetProgramId, "GetProgramId"},
182 {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, 176 {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"},
@@ -193,11 +187,11 @@ private:
193 187
194 LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); 188 LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id);
195 189
196 const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { 190 auto list = kernel.GetProcessList();
197 return proc->GetProcessId() == process_id; 191 auto process = SearchProcessList(
198 }); 192 list, [process_id](auto& p) { return p->GetProcessId() == process_id; });
199 193
200 if (!process.has_value()) { 194 if (process.IsNull()) {
201 IPC::ResponseBuilder rb{ctx, 2}; 195 IPC::ResponseBuilder rb{ctx, 2};
202 rb.Push(ResultProcessNotFound); 196 rb.Push(ResultProcessNotFound);
203 return; 197 return;
@@ -205,7 +199,7 @@ private:
205 199
206 IPC::ResponseBuilder rb{ctx, 4}; 200 IPC::ResponseBuilder rb{ctx, 4};
207 rb.Push(ResultSuccess); 201 rb.Push(ResultSuccess);
208 rb.Push((*process)->GetProgramId()); 202 rb.Push(process->GetProgramId());
209 } 203 }
210 204
211 void AtmosphereGetProcessId(HLERequestContext& ctx) { 205 void AtmosphereGetProcessId(HLERequestContext& ctx) {
@@ -214,11 +208,11 @@ private:
214 208
215 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); 209 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
216 210
217 const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { 211 auto list = system.Kernel().GetProcessList();
218 return proc->GetProgramId() == program_id; 212 auto process = SearchProcessList(
219 }); 213 list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
220 214
221 if (!process.has_value()) { 215 if (process.IsNull()) {
222 IPC::ResponseBuilder rb{ctx, 2}; 216 IPC::ResponseBuilder rb{ctx, 2};
223 rb.Push(ResultProcessNotFound); 217 rb.Push(ResultProcessNotFound);
224 return; 218 return;
@@ -226,16 +220,13 @@ private:
226 220
227 IPC::ResponseBuilder rb{ctx, 4}; 221 IPC::ResponseBuilder rb{ctx, 4};
228 rb.Push(ResultSuccess); 222 rb.Push(ResultSuccess);
229 rb.Push((*process)->GetProcessId()); 223 rb.Push(process->GetProcessId());
230 } 224 }
231
232 const std::vector<Kernel::KProcess*>& process_list;
233}; 225};
234 226
235class Shell final : public ServiceFramework<Shell> { 227class Shell final : public ServiceFramework<Shell> {
236public: 228public:
237 explicit Shell(Core::System& system_) 229 explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} {
238 : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} {
239 // clang-format off 230 // clang-format off
240 static const FunctionInfo functions[] = { 231 static const FunctionInfo functions[] = {
241 {0, nullptr, "LaunchProgram"}, 232 {0, nullptr, "LaunchProgram"},
@@ -257,10 +248,9 @@ public:
257private: 248private:
258 void GetApplicationProcessIdForShell(HLERequestContext& ctx) { 249 void GetApplicationProcessIdForShell(HLERequestContext& ctx) {
259 LOG_DEBUG(Service_PM, "called"); 250 LOG_DEBUG(Service_PM, "called");
260 GetApplicationPidGeneric(ctx, kernel.GetProcessList()); 251 auto list = kernel.GetProcessList();
252 GetApplicationPidGeneric(ctx, list);
261 } 253 }
262
263 const Kernel::KernelCore& kernel;
264}; 254};
265 255
266void LoopProcess(Core::System& system) { 256void LoopProcess(Core::System& system) {
@@ -268,8 +258,7 @@ void LoopProcess(Core::System& system) {
268 258
269 server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system)); 259 server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system));
270 server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); 260 server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system));
271 server_manager->RegisterNamedService( 261 server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system));
272 "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList()));
273 server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); 262 server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system));
274 ServerManager::RunServer(std::move(server_manager)); 263 ServerManager::RunServer(std::move(server_manager));
275} 264}
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp
index 15edb23e0..8ef49387d 100644
--- a/src/core/hle/service/server_manager.cpp
+++ b/src/core/hle/service/server_manager.cpp
@@ -256,8 +256,13 @@ Result ServerManager::WaitAndProcessImpl() {
256 256
257 // Wait for a signal. 257 // Wait for a signal.
258 s32 out_index{-1}; 258 s32 out_index{-1};
259 R_TRY(Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &out_index, wait_objs.data(), 259 R_TRY_CATCH(Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &out_index,
260 num_objs, -1)); 260 wait_objs.data(), num_objs, -1)) {
261 R_CATCH(Kernel::ResultSessionClosed) {
262 // On session closed, index is updated and we don't want to return an error.
263 }
264 }
265 R_END_TRY_CATCH;
261 ASSERT(out_index >= 0 && out_index < num_objs); 266 ASSERT(out_index >= 0 && out_index < num_objs);
262 267
263 // Set the output index. 268 // Set the output index.
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 71ce9be50..e2d9cd98a 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -71,18 +71,7 @@ size_t Display::GetNumLayers() const {
71 return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); }); 71 return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); });
72} 72}
73 73
74Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) { 74Kernel::KReadableEvent* Display::GetVSyncEvent() {
75 if (got_vsync_event) {
76 return ResultPermissionDenied;
77 }
78
79 got_vsync_event = true;
80
81 *out_vsync_event = GetVSyncEventUnchecked();
82 return ResultSuccess;
83}
84
85Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
86 return &vsync_event->GetReadableEvent(); 75 return &vsync_event->GetReadableEvent();
87} 76}
88 77
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 1d9360b96..7e68ee79b 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -74,16 +74,8 @@ public:
74 74
75 std::size_t GetNumLayers() const; 75 std::size_t GetNumLayers() const;
76 76
77 /**
78 * Gets the internal vsync event.
79 *
80 * @returns The internal Vsync event if it has not yet been retrieved,
81 * VI::ResultPermissionDenied otherwise.
82 */
83 [[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event);
84
85 /// Gets the internal vsync event. 77 /// Gets the internal vsync event.
86 Kernel::KReadableEvent* GetVSyncEventUnchecked(); 78 Kernel::KReadableEvent* GetVSyncEvent();
87 79
88 /// Signals the internal vsync event. 80 /// Signals the internal vsync event.
89 void SignalVSyncEvent(); 81 void SignalVSyncEvent();
@@ -104,7 +96,6 @@ public:
104 /// Resets the display for a new connection. 96 /// Resets the display for a new connection.
105 void Reset() { 97 void Reset() {
106 layers.clear(); 98 layers.clear();
107 got_vsync_event = false;
108 } 99 }
109 100
110 /// Attempts to find a layer with the given ID. 101 /// Attempts to find a layer with the given ID.
@@ -133,7 +124,6 @@ private:
133 124
134 std::vector<std::unique_ptr<Layer>> layers; 125 std::vector<std::unique_ptr<Layer>> layers;
135 Kernel::KEvent* vsync_event{}; 126 Kernel::KEvent* vsync_event{};
136 bool got_vsync_event{false};
137}; 127};
138 128
139} // namespace Service::VI 129} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 9ab8788e3..39d5be90d 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -343,8 +343,8 @@ private:
343 343
344class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { 344class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
345public: 345public:
346 explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_) 346 explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
347 : ServiceFramework{system_, "IManagerDisplayService"}, nv_flinger{nv_flinger_} { 347 : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} {
348 // clang-format off 348 // clang-format off
349 static const FunctionInfo functions[] = { 349 static const FunctionInfo functions[] = {
350 {200, nullptr, "AllocateProcessHeapBlock"}, 350 {200, nullptr, "AllocateProcessHeapBlock"},
@@ -440,7 +440,7 @@ private:
440 IPC::RequestParser rp{ctx}; 440 IPC::RequestParser rp{ctx};
441 const u64 display = rp.Pop<u64>(); 441 const u64 display = rp.Pop<u64>();
442 442
443 const Result rc = nv_flinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; 443 const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
444 444
445 IPC::ResponseBuilder rb{ctx, 2}; 445 IPC::ResponseBuilder rb{ctx, 2};
446 rb.Push(rc); 446 rb.Push(rc);
@@ -457,7 +457,7 @@ private:
457 "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", 457 "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
458 unknown, display, aruid); 458 unknown, display, aruid);
459 459
460 const auto layer_id = nv_flinger.CreateLayer(display); 460 const auto layer_id = nvnflinger.CreateLayer(display);
461 if (!layer_id) { 461 if (!layer_id) {
462 LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); 462 LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
463 IPC::ResponseBuilder rb{ctx, 2}; 463 IPC::ResponseBuilder rb{ctx, 2};
@@ -494,14 +494,14 @@ private:
494 rb.Push(ResultSuccess); 494 rb.Push(ResultSuccess);
495 } 495 }
496 496
497 Nvnflinger::Nvnflinger& nv_flinger; 497 Nvnflinger::Nvnflinger& nvnflinger;
498}; 498};
499 499
500class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 500class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
501public: 501public:
502 IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, 502 IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_,
503 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) 503 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
504 : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_}, 504 : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_},
505 hos_binder_driver_server{hos_binder_driver_server_} { 505 hos_binder_driver_server{hos_binder_driver_server_} {
506 506
507 static const FunctionInfo functions[] = { 507 static const FunctionInfo functions[] = {
@@ -564,7 +564,7 @@ private:
564 564
565 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 565 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
566 rb.Push(ResultSuccess); 566 rb.Push(ResultSuccess);
567 rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger); 567 rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger);
568 } 568 }
569 569
570 void GetManagerDisplayService(HLERequestContext& ctx) { 570 void GetManagerDisplayService(HLERequestContext& ctx) {
@@ -572,7 +572,7 @@ private:
572 572
573 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 573 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
574 rb.Push(ResultSuccess); 574 rb.Push(ResultSuccess);
575 rb.PushIpcInterface<IManagerDisplayService>(system, nv_flinger); 575 rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger);
576 } 576 }
577 577
578 void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { 578 void GetIndirectDisplayTransactionService(HLERequestContext& ctx) {
@@ -607,7 +607,7 @@ private:
607 607
608 ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); 608 ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
609 609
610 const auto display_id = nv_flinger.OpenDisplay(name); 610 const auto display_id = nvnflinger.OpenDisplay(name);
611 if (!display_id) { 611 if (!display_id) {
612 LOG_ERROR(Service_VI, "Display not found! display_name={}", name); 612 LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
613 IPC::ResponseBuilder rb{ctx, 2}; 613 IPC::ResponseBuilder rb{ctx, 2};
@@ -624,7 +624,7 @@ private:
624 IPC::RequestParser rp{ctx}; 624 IPC::RequestParser rp{ctx};
625 const u64 display_id = rp.Pop<u64>(); 625 const u64 display_id = rp.Pop<u64>();
626 626
627 const Result rc = nv_flinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; 627 const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
628 628
629 IPC::ResponseBuilder rb{ctx, 2}; 629 IPC::ResponseBuilder rb{ctx, 2};
630 rb.Push(rc); 630 rb.Push(rc);
@@ -703,7 +703,7 @@ private:
703 703
704 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); 704 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
705 705
706 const auto display_id = nv_flinger.OpenDisplay(display_name); 706 const auto display_id = nvnflinger.OpenDisplay(display_name);
707 if (!display_id) { 707 if (!display_id) {
708 LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); 708 LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
709 IPC::ResponseBuilder rb{ctx, 2}; 709 IPC::ResponseBuilder rb{ctx, 2};
@@ -711,7 +711,7 @@ private:
711 return; 711 return;
712 } 712 }
713 713
714 const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id); 714 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id);
715 if (!buffer_queue_id) { 715 if (!buffer_queue_id) {
716 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); 716 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
717 IPC::ResponseBuilder rb{ctx, 2}; 717 IPC::ResponseBuilder rb{ctx, 2};
@@ -719,7 +719,7 @@ private:
719 return; 719 return;
720 } 720 }
721 721
722 nv_flinger.OpenLayer(layer_id); 722 nvnflinger.OpenLayer(layer_id);
723 723
724 android::OutputParcel parcel; 724 android::OutputParcel parcel;
725 parcel.WriteInterface(NativeWindow{*buffer_queue_id}); 725 parcel.WriteInterface(NativeWindow{*buffer_queue_id});
@@ -737,7 +737,7 @@ private:
737 737
738 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); 738 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
739 739
740 nv_flinger.CloseLayer(layer_id); 740 nvnflinger.CloseLayer(layer_id);
741 741
742 IPC::ResponseBuilder rb{ctx, 2}; 742 IPC::ResponseBuilder rb{ctx, 2};
743 rb.Push(ResultSuccess); 743 rb.Push(ResultSuccess);
@@ -753,7 +753,7 @@ private:
753 753
754 // TODO(Subv): What's the difference between a Stray and a Managed layer? 754 // TODO(Subv): What's the difference between a Stray and a Managed layer?
755 755
756 const auto layer_id = nv_flinger.CreateLayer(display_id); 756 const auto layer_id = nvnflinger.CreateLayer(display_id);
757 if (!layer_id) { 757 if (!layer_id) {
758 LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); 758 LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
759 IPC::ResponseBuilder rb{ctx, 2}; 759 IPC::ResponseBuilder rb{ctx, 2};
@@ -761,7 +761,7 @@ private:
761 return; 761 return;
762 } 762 }
763 763
764 const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id); 764 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
765 if (!buffer_queue_id) { 765 if (!buffer_queue_id) {
766 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); 766 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
767 IPC::ResponseBuilder rb{ctx, 2}; 767 IPC::ResponseBuilder rb{ctx, 2};
@@ -785,7 +785,7 @@ private:
785 const u64 layer_id = rp.Pop<u64>(); 785 const u64 layer_id = rp.Pop<u64>();
786 786
787 LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); 787 LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
788 nv_flinger.DestroyLayer(layer_id); 788 nvnflinger.DestroyLayer(layer_id);
789 789
790 IPC::ResponseBuilder rb{ctx, 2}; 790 IPC::ResponseBuilder rb{ctx, 2};
791 rb.Push(ResultSuccess); 791 rb.Push(ResultSuccess);
@@ -798,7 +798,7 @@ private:
798 LOG_DEBUG(Service_VI, "called. display_id={}", display_id); 798 LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
799 799
800 Kernel::KReadableEvent* vsync_event{}; 800 Kernel::KReadableEvent* vsync_event{};
801 const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id); 801 const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id);
802 if (result != ResultSuccess) { 802 if (result != ResultSuccess) {
803 if (result == ResultNotFound) { 803 if (result == ResultNotFound) {
804 LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); 804 LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
@@ -808,6 +808,12 @@ private:
808 rb.Push(result); 808 rb.Push(result);
809 return; 809 return;
810 } 810 }
811 if (vsync_event_fetched) {
812 IPC::ResponseBuilder rb{ctx, 2};
813 rb.Push(VI::ResultPermissionDenied);
814 return;
815 }
816 vsync_event_fetched = true;
811 817
812 IPC::ResponseBuilder rb{ctx, 2, 1}; 818 IPC::ResponseBuilder rb{ctx, 2, 1};
813 rb.Push(ResultSuccess); 819 rb.Push(ResultSuccess);
@@ -899,8 +905,9 @@ private:
899 } 905 }
900 } 906 }
901 907
902 Nvnflinger::Nvnflinger& nv_flinger; 908 Nvnflinger::Nvnflinger& nvnflinger;
903 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; 909 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
910 bool vsync_event_fetched{false};
904}; 911};
905 912
906static bool IsValidServiceAccess(Permission permission, Policy policy) { 913static bool IsValidServiceAccess(Permission permission, Policy policy) {
@@ -916,7 +923,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
916} 923}
917 924
918void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, 925void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
919 Nvnflinger::Nvnflinger& nv_flinger, 926 Nvnflinger::Nvnflinger& nvnflinger,
920 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, 927 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
921 Permission permission) { 928 Permission permission) {
922 IPC::RequestParser rp{ctx}; 929 IPC::RequestParser rp{ctx};
@@ -931,19 +938,19 @@ void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
931 938
932 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 939 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
933 rb.Push(ResultSuccess); 940 rb.Push(ResultSuccess);
934 rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server); 941 rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server);
935} 942}
936 943
937void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, 944void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
938 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { 945 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) {
939 auto server_manager = std::make_unique<ServerManager>(system); 946 auto server_manager = std::make_unique<ServerManager>(system);
940 947
941 server_manager->RegisterNamedService( 948 server_manager->RegisterNamedService(
942 "vi:m", std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server)); 949 "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server));
943 server_manager->RegisterNamedService( 950 server_manager->RegisterNamedService(
944 "vi:s", std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server)); 951 "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server));
945 server_manager->RegisterNamedService( 952 server_manager->RegisterNamedService(
946 "vi:u", std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server)); 953 "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server));
947 ServerManager::RunServer(std::move(server_manager)); 954 ServerManager::RunServer(std::move(server_manager));
948} 955}
949 956
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index a35b62f97..ee4bcbcfa 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -48,7 +48,7 @@ void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
48 Permission permission); 48 Permission permission);
49} // namespace detail 49} // namespace detail
50 50
51void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, 51void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
52 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); 52 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
53 53
54} // namespace Service::VI 54} // namespace Service::VI