diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index d9decc104d..94268d1278 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -358,17 +358,21 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
     return out;
 }
 
-static std::shared_ptr<NCA> GetNCAFromXCIForID(std::shared_ptr<XCI> xci, const NcaID& id) {
-    const auto filename = fmt::format("{}.nca", Common::HexArrayToString(id, false));
-    const auto iter =
-        std::find_if(xci->GetNCAs().begin(), xci->GetNCAs().end(),
-                     [&filename](std::shared_ptr<NCA> nca) { return nca->GetName() == filename; });
-    return iter == xci->GetNCAs().end() ? nullptr : *iter;
+static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) {
+    const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
+    if (file == nullptr)
+        return nullptr;
+    return std::make_shared<NCA>(file);
 }
 
 InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists,
                                             const VfsCopyFunction& copy) {
-    const auto& ncas = xci->GetNCAs();
+    return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy);
+}
+
+InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists,
+                                            const VfsCopyFunction& copy) {
+    const auto& ncas = nsp->GetNCAsCollapsed();
     const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) {
         return nca->GetType() == NCAContentType::Meta;
     });
@@ -392,7 +396,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overw
     const auto cnmt_file = section0->GetFiles()[0];
     const CNMT cnmt(cnmt_file);
     for (const auto& record : cnmt.GetContentRecords()) {
-        const auto nca = GetNCAFromXCIForID(xci, record.nca_id);
+        const auto nca = GetNCAFromNSPForID(nsp, record.nca_id);
         if (nca == nullptr)
             return InstallResult::ErrorCopyFailed;
         const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id);
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index fe2cdc3d99..50e26f8fb2 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -89,10 +89,12 @@ public:
         boost::optional<ContentRecordType> record_type = boost::none,
         boost::optional<u64> title_id = boost::none) const;
 
-    // Raw copies all the ncas from the xci to the csache. Does some quick checks to make sure there
-    // is a meta NCA and all of them are accessible.
+    // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
+    // there is a meta NCA and all of them are accessible.
     InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false,
                                const VfsCopyFunction& copy = &VfsRawCopy);
+    InstallResult InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists = false,
+                               const VfsCopyFunction& copy = &VfsRawCopy);
 
     // Due to the fact that we must use Meta-type NCAs to determine the existance of files, this
     // poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 262e33487e..c4eda4babf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -806,22 +806,34 @@ void GMainWindow::OnMenuInstallToNAND() {
                QMessageBox::Yes;
     };
 
-    if (filename.endsWith("xci", Qt::CaseInsensitive)) {
-        const auto xci = std::make_shared<FileSys::XCI>(
-            vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
-        if (xci->GetStatus() != Loader::ResultStatus::Success) {
+    if (filename.endsWith("xci", Qt::CaseInsensitive) ||
+        filename.endsWith("nsp", Qt::CaseInsensitive)) {
+
+        std::shared_ptr<FileSys::NSP> nsp;
+        if (filename.endsWith("nsp", Qt::CaseInsensitive)) {
+            nsp = std::make_shared<FileSys::NSP>(
+                vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
+            if (!nsp->IsExtractedType())
+                failed();
+        } else {
+            const auto xci = std::make_shared<FileSys::XCI>(
+                vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
+            nsp = xci->GetSecurePartitionNSP();
+        }
+
+        if (nsp->GetStatus() != Loader::ResultStatus::Success) {
             failed();
             return;
         }
         const auto res =
-            Service::FileSystem::GetUserNANDContents()->InstallEntry(xci, false, qt_raw_copy);
+            Service::FileSystem::GetUserNANDContents()->InstallEntry(nsp, false, qt_raw_copy);
         if (res == FileSys::InstallResult::Success) {
             success();
         } else {
             if (res == FileSys::InstallResult::ErrorAlreadyExists) {
                 if (overwrite()) {
                     const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry(
-                        xci, true, qt_raw_copy);
+                        nsp, true, qt_raw_copy);
                     if (res2 == FileSys::InstallResult::Success) {
                         success();
                     } else {