summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/registered_cache.cpp37
-rw-r--r--src/core/hle/kernel/k_process.cpp25
-rw-r--r--src/core/hle/kernel/k_process.h7
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp11
-rw-r--r--src/core/hle/service/ssl/ssl.cpp10
-rw-r--r--src/core/hle/service/ssl/ssl_backend_openssl.cpp3
-rw-r--r--src/core/hle/service/ssl/ssl_backend_schannel.cpp25
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp2
-rw-r--r--src/core/loader/kip.cpp2
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/reporter.cpp4
-rw-r--r--src/yuzu/main.cpp38
-rw-r--r--src/yuzu/main.h1
14 files changed, 124 insertions, 45 deletions
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index a28af3594..f70adab82 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -606,9 +606,9 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
606 const auto result = RemoveExistingEntry(title_id); 606 const auto result = RemoveExistingEntry(title_id);
607 607
608 // Install Metadata File 608 // Install Metadata File
609 const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); 609 const auto meta_result = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data);
610 if (res != InstallResult::Success) { 610 if (meta_result != InstallResult::Success) {
611 return res; 611 return meta_result;
612 } 612 }
613 613
614 // Install all the other NCAs 614 // Install all the other NCAs
@@ -621,9 +621,19 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
621 if (nca == nullptr) { 621 if (nca == nullptr) {
622 return InstallResult::ErrorCopyFailed; 622 return InstallResult::ErrorCopyFailed;
623 } 623 }
624 const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); 624 if (nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
625 if (res2 != InstallResult::Success) { 625 nca->GetTitleId() != title_id) {
626 return res2; 626 // Create fake cnmt for patch to multiprogram application
627 const auto sub_nca_result =
628 InstallEntry(*nca, TitleType::Update, overwrite_if_exists, copy);
629 if (sub_nca_result != InstallResult::Success) {
630 return sub_nca_result;
631 }
632 continue;
633 }
634 const auto nca_result = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id);
635 if (nca_result != InstallResult::Success) {
636 return nca_result;
627 } 637 }
628 } 638 }
629 639
@@ -663,6 +673,8 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
663} 673}
664 674
665bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { 675bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
676 bool removed_data = false;
677
666 const auto delete_nca = [this](const NcaID& id) { 678 const auto delete_nca = [this](const NcaID& id) {
667 const auto path = GetRelativePathFromNcaID(id, false, true, false); 679 const auto path = GetRelativePathFromNcaID(id, false, true, false);
668 680
@@ -706,11 +718,18 @@ bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
706 const auto deleted_html = delete_nca(html_id); 718 const auto deleted_html = delete_nca(html_id);
707 const auto deleted_legal = delete_nca(legal_id); 719 const auto deleted_legal = delete_nca(legal_id);
708 720
709 return deleted_meta && (deleted_meta || deleted_program || deleted_data || 721 removed_data |= (deleted_meta || deleted_program || deleted_data || deleted_control ||
710 deleted_control || deleted_html || deleted_legal); 722 deleted_html || deleted_legal);
711 } 723 }
712 724
713 return false; 725 // If patch entries for any program exist in yuzu meta, remove them
726 for (u8 i = 0; i < 0x10; i++) {
727 const auto meta_dir = dir->CreateDirectoryRelative("yuzu_meta");
728 const auto filename = GetCNMTName(TitleType::Update, title_id + i);
729 removed_data |= meta_dir->DeleteFile(filename);
730 }
731
732 return removed_data;
714} 733}
715 734
716InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, 735InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index e573e2a57..703049ede 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -38,7 +38,7 @@ namespace {
38 */ 38 */
39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, 39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
40 KProcessAddress stack_top) { 40 KProcessAddress stack_top) {
41 const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart(); 41 const KProcessAddress entry_point = owner_process.GetEntryPoint();
42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); 42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
43 43
44 KThread* thread = KThread::Create(system.Kernel()); 44 KThread* thread = KThread::Create(system.Kernel());
@@ -358,6 +358,21 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
358 m_system_resource_size = metadata.GetSystemResourceSize(); 358 m_system_resource_size = metadata.GetSystemResourceSize();
359 m_image_size = code_size; 359 m_image_size = code_size;
360 360
361 if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) {
362 // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
363 // However, some (buggy) programs/libraries like skyline incorrectly depend on the
364 // existence of ASLR pages before the entry point, so we will adjust the load address
365 // to point to about 2GiB into the ASLR region.
366 m_code_address = 0x8000'0000;
367 } else {
368 // All other processes can be mapped at the beginning of the code region.
369 if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is36Bit) {
370 m_code_address = 0x800'0000;
371 } else {
372 m_code_address = 0x20'0000;
373 }
374 }
375
361 KScopedResourceReservation memory_reservation( 376 KScopedResourceReservation memory_reservation(
362 m_resource_limit, LimitableResource::PhysicalMemoryMax, code_size + m_system_resource_size); 377 m_resource_limit, LimitableResource::PhysicalMemoryMax, code_size + m_system_resource_size);
363 if (!memory_reservation.Succeeded()) { 378 if (!memory_reservation.Succeeded()) {
@@ -368,15 +383,15 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
368 // Initialize process address space 383 // Initialize process address space
369 if (const Result result{m_page_table.InitializeForProcess( 384 if (const Result result{m_page_table.InitializeForProcess(
370 metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application, 385 metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
371 0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), m_resource_limit, 386 this->GetEntryPoint(), code_size, std::addressof(m_kernel.GetAppSystemResource()),
372 m_kernel.System().ApplicationMemory())}; 387 m_resource_limit, m_kernel.System().ApplicationMemory())};
373 result.IsError()) { 388 result.IsError()) {
374 R_RETURN(result); 389 R_RETURN(result);
375 } 390 }
376 391
377 // Map process code region 392 // Map process code region
378 if (const Result result{m_page_table.MapProcessCode(m_page_table.GetCodeRegionStart(), 393 if (const Result result{m_page_table.MapProcessCode(this->GetEntryPoint(), code_size / PageSize,
379 code_size / PageSize, KMemoryState::Code, 394 KMemoryState::Code,
380 KMemoryPermission::None)}; 395 KMemoryPermission::None)};
381 result.IsError()) { 396 result.IsError()) {
382 R_RETURN(result); 397 R_RETURN(result);
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index c9b37e138..4fdeaf11a 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -177,6 +177,10 @@ public:
177 return m_program_id; 177 return m_program_id;
178 } 178 }
179 179
180 KProcessAddress GetEntryPoint() const {
181 return m_code_address;
182 }
183
180 /// Gets the resource limit descriptor for this process 184 /// Gets the resource limit descriptor for this process
181 KResourceLimit* GetResourceLimit() const; 185 KResourceLimit* GetResourceLimit() const;
182 186
@@ -485,6 +489,9 @@ private:
485 /// Address indicating the location of the process' dedicated TLS region. 489 /// Address indicating the location of the process' dedicated TLS region.
486 KProcessAddress m_plr_address = 0; 490 KProcessAddress m_plr_address = 0;
487 491
492 /// Address indicating the location of the process's entry point.
493 KProcessAddress m_code_address = 0;
494
488 /// Random values for svcGetInfo RandomEntropy 495 /// Random values for svcGetInfo RandomEntropy
489 std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{}; 496 std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{};
490 497
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 4c1ea1a5b..508db7360 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -4,6 +4,7 @@
4#include <utility> 4#include <utility>
5 5
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/fs/fs.h"
7#include "common/fs/path_util.h" 8#include "common/fs/path_util.h"
8#include "common/settings.h" 9#include "common/settings.h"
9#include "core/core.h" 10#include "core/core.h"
@@ -154,10 +155,18 @@ Result VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
154 std::string src_path(Common::FS::SanitizePath(src_path_)); 155 std::string src_path(Common::FS::SanitizePath(src_path_));
155 std::string dest_path(Common::FS::SanitizePath(dest_path_)); 156 std::string dest_path(Common::FS::SanitizePath(dest_path_));
156 auto src = backing->GetFileRelative(src_path); 157 auto src = backing->GetFileRelative(src_path);
158 auto dst = backing->GetFileRelative(dest_path);
157 if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { 159 if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) {
158 // Use more-optimized vfs implementation rename. 160 // Use more-optimized vfs implementation rename.
159 if (src == nullptr) 161 if (src == nullptr) {
160 return FileSys::ERROR_PATH_NOT_FOUND; 162 return FileSys::ERROR_PATH_NOT_FOUND;
163 }
164
165 if (dst && Common::FS::Exists(dst->GetFullPath())) {
166 LOG_ERROR(Service_FS, "File at new_path={} already exists", dst->GetFullPath());
167 return FileSys::ERROR_PATH_ALREADY_EXISTS;
168 }
169
161 if (!src->Rename(Common::FS::GetFilename(dest_path))) { 170 if (!src->Rename(Common::FS::GetFilename(dest_path))) {
162 // TODO(DarkLordZach): Find a better error code for this 171 // TODO(DarkLordZach): Find a better error code for this
163 return ResultUnknown; 172 return ResultUnknown;
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 2cba9e5c9..6c8427b0d 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -139,7 +139,6 @@ private:
139 bool do_not_close_socket = false; 139 bool do_not_close_socket = false;
140 bool get_server_cert_chain = false; 140 bool get_server_cert_chain = false;
141 std::shared_ptr<Network::SocketBase> socket; 141 std::shared_ptr<Network::SocketBase> socket;
142 bool did_set_host_name = false;
143 bool did_handshake = false; 142 bool did_handshake = false;
144 143
145 Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { 144 Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) {
@@ -174,11 +173,7 @@ private:
174 Result SetHostNameImpl(const std::string& hostname) { 173 Result SetHostNameImpl(const std::string& hostname) {
175 LOG_DEBUG(Service_SSL, "called. hostname={}", hostname); 174 LOG_DEBUG(Service_SSL, "called. hostname={}", hostname);
176 ASSERT(!did_handshake); 175 ASSERT(!did_handshake);
177 Result res = backend->SetHostName(hostname); 176 return backend->SetHostName(hostname);
178 if (res == ResultSuccess) {
179 did_set_host_name = true;
180 }
181 return res;
182 } 177 }
183 178
184 Result SetVerifyOptionImpl(u32 option) { 179 Result SetVerifyOptionImpl(u32 option) {
@@ -208,9 +203,6 @@ private:
208 203
209 Result DoHandshakeImpl() { 204 Result DoHandshakeImpl() {
210 ASSERT_OR_EXECUTE(!did_handshake && socket, { return ResultNoSocket; }); 205 ASSERT_OR_EXECUTE(!did_handshake && socket, { return ResultNoSocket; });
211 ASSERT_OR_EXECUTE_MSG(
212 did_set_host_name, { return ResultInternalError; },
213 "Expected SetHostName before DoHandshake");
214 Result res = backend->DoHandshake(); 206 Result res = backend->DoHandshake();
215 did_handshake = res.IsSuccess(); 207 did_handshake = res.IsSuccess();
216 return res; 208 return res;
diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp
index b2dd37cd4..5714e6f3c 100644
--- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp
+++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp
@@ -167,9 +167,8 @@ public:
167 } 167 }
168 168
169 ~SSLConnectionBackendOpenSSL() { 169 ~SSLConnectionBackendOpenSSL() {
170 // these are null-tolerant: 170 // this is null-tolerant:
171 SSL_free(ssl); 171 SSL_free(ssl);
172 BIO_free(bio);
173 } 172 }
174 173
175 static void KeyLogCallback(const SSL* ssl, const char* line) { 174 static void KeyLogCallback(const SSL* ssl, const char* line) {
diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp
index bda12b761..d834a0c1f 100644
--- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp
+++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp
@@ -31,9 +31,9 @@ CredHandle cred_handle;
31static void OneTimeInit() { 31static void OneTimeInit() {
32 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; 32 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
33 schannel_cred.dwFlags = 33 schannel_cred.dwFlags =
34 SCH_USE_STRONG_CRYPTO | // don't allow insecure protocols 34 SCH_USE_STRONG_CRYPTO | // don't allow insecure protocols
35 SCH_CRED_AUTO_CRED_VALIDATION | // validate certs 35 SCH_CRED_NO_SERVERNAME_CHECK | // don't validate server names
36 SCH_CRED_NO_DEFAULT_CREDS; // don't automatically present a client certificate 36 SCH_CRED_NO_DEFAULT_CREDS; // don't automatically present a client certificate
37 // ^ I'm assuming that nobody would want to connect Yuzu to a 37 // ^ I'm assuming that nobody would want to connect Yuzu to a
38 // service that requires some OS-provided corporate client 38 // service that requires some OS-provided corporate client
39 // certificate, and presenting one to some arbitrary server 39 // certificate, and presenting one to some arbitrary server
@@ -227,16 +227,15 @@ public:
227 ciphertext_read_buf.size()); 227 ciphertext_read_buf.size());
228 } 228 }
229 229
230 const SECURITY_STATUS ret = 230 char* hostname_ptr = hostname ? const_cast<char*>(hostname->c_str()) : nullptr;
231 InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt : nullptr, 231 const SECURITY_STATUS ret = InitializeSecurityContextA(
232 // Caller ensured we have set a hostname: 232 &cred_handle, initial_call_done ? &ctxt : nullptr, hostname_ptr, req,
233 const_cast<char*>(hostname.value().c_str()), req, 233 0, // Reserved1
234 0, // Reserved1 234 0, // TargetDataRep not used with Schannel
235 0, // TargetDataRep not used with Schannel 235 initial_call_done ? &input_desc : nullptr,
236 initial_call_done ? &input_desc : nullptr, 236 0, // Reserved2
237 0, // Reserved2 237 initial_call_done ? nullptr : &ctxt, &output_desc, &attr,
238 initial_call_done ? nullptr : &ctxt, &output_desc, &attr, 238 nullptr); // ptsExpiry
239 nullptr); // ptsExpiry
240 239
241 if (output_buffers[0].pvBuffer) { 240 if (output_buffers[0].pvBuffer) {
242 const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer), 241 const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer),
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index e04ad19db..f4eaf3331 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
153 153
154 // Load NSO modules 154 // Load NSO modules
155 modules.clear(); 155 modules.clear();
156 const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())}; 156 const VAddr base_address{GetInteger(process.GetEntryPoint())};
157 VAddr next_load_addr{base_address}; 157 VAddr next_load_addr{base_address};
158 const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), 158 const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
159 system.GetContentProvider()}; 159 system.GetContentProvider()};
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
index ffe976b94..d722459c6 100644
--- a/src/core/loader/kip.cpp
+++ b/src/core/loader/kip.cpp
@@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
96 } 96 }
97 97
98 codeset.memory = std::move(program_image); 98 codeset.memory = std::move(program_image);
99 const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); 99 const VAddr base_address = GetInteger(process.GetEntryPoint());
100 process.LoadModule(std::move(codeset), base_address); 100 process.LoadModule(std::move(codeset), base_address);
101 101
102 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); 102 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 506808b5d..d7562b4bc 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
203 203
204 // Load codeset for current process 204 // Load codeset for current process
205 codeset.memory = std::move(program_image); 205 codeset.memory = std::move(program_image);
206 process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart()); 206 process.LoadModule(std::move(codeset), process.GetEntryPoint());
207 207
208 return true; 208 return true;
209} 209}
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 74cc9579f..549822506 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
167 modules.clear(); 167 modules.clear();
168 168
169 // Load module 169 // Load module
170 const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); 170 const VAddr base_address = GetInteger(process.GetEntryPoint());
171 if (!LoadModule(process, system, *file, base_address, true, true)) { 171 if (!LoadModule(process, system, *file, base_address, true, true)) {
172 return {ResultStatus::ErrorLoadingNSO, {}}; 172 return {ResultStatus::ErrorLoadingNSO, {}};
173 } 173 }
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index b5b3e7eda..ed875d444 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) {
117 arm.SaveContext(context); 117 arm.SaveContext(context);
118 118
119 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", 119 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
120 GetInteger(process->GetPageTable().GetCodeRegionStart()), 120 GetInteger(process->GetEntryPoint()), context.sp, context.pc,
121 context.sp, context.pc, context.pstate, context.cpu_registers); 121 context.pstate, context.cpu_registers);
122} 122}
123 123
124json GetBacktraceData(Core::System& system) { 124json GetBacktraceData(Core::System& system) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a9d035f3d..8e933af64 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1811,6 +1811,43 @@ bool GMainWindow::SelectAndSetCurrentUser(
1811 return true; 1811 return true;
1812} 1812}
1813 1813
1814void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
1815 // Ensure all NCAs are registered before launching the game
1816 const auto file = vfs->OpenFile(filepath, FileSys::Mode::Read);
1817 if (!file) {
1818 return;
1819 }
1820
1821 auto loader = Loader::GetLoader(*system, file);
1822 if (!loader) {
1823 return;
1824 }
1825
1826 const auto file_type = loader->GetFileType();
1827 if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
1828 return;
1829 }
1830
1831 u64 program_id = 0;
1832 const auto res2 = loader->ReadProgramId(program_id);
1833 if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
1834 provider->AddEntry(FileSys::TitleType::Application,
1835 FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()), program_id,
1836 file);
1837 } else if (res2 == Loader::ResultStatus::Success &&
1838 (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
1839 const auto nsp = file_type == Loader::FileType::NSP
1840 ? std::make_shared<FileSys::NSP>(file)
1841 : FileSys::XCI{file}.GetSecurePartitionNSP();
1842 for (const auto& title : nsp->GetNCAs()) {
1843 for (const auto& entry : title.second) {
1844 provider->AddEntry(entry.first.first, entry.first.second, title.first,
1845 entry.second->GetBaseFile());
1846 }
1847 }
1848 }
1849}
1850
1814void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, 1851void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
1815 StartGameType type) { 1852 StartGameType type) {
1816 LOG_INFO(Frontend, "yuzu starting..."); 1853 LOG_INFO(Frontend, "yuzu starting...");
@@ -1825,6 +1862,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1825 1862
1826 last_filename_booted = filename; 1863 last_filename_booted = filename;
1827 1864
1865 ConfigureFilesystemProvider(filename.toStdString());
1828 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); 1866 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
1829 const auto loader = Loader::GetLoader(*system, v_file, program_id, program_index); 1867 const auto loader = Loader::GetLoader(*system, v_file, program_id, program_index);
1830 1868
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 2cfb96257..1b7055122 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -399,6 +399,7 @@ private:
399 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); 399 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
400 bool CheckDarkMode(); 400 bool CheckDarkMode();
401 bool CheckSystemArchiveDecryption(); 401 bool CheckSystemArchiveDecryption();
402 void ConfigureFilesystemProvider(const std::string& filepath);
402 403
403 QString GetTasStateDescription() const; 404 QString GetTasStateDescription() const;
404 bool CreateShortcut(const std::string& shortcut_path, const std::string& title, 405 bool CreateShortcut(const std::string& shortcut_path, const std::string& title,