diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 395eea8ae0bf37d80a6795a6cc97c7aeaae9ca87..e897d99130f6f74a39dd379be3dd24066902358a 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -5,6 +5,7 @@
 #include <array>
 #include <string>
 #include <core/loader/loader.h>
+#include "common/logging/log.h"
 #include "core/file_sys/card_image.h"
 #include "core/file_sys/partition_filesystem.h"
 #include "core/file_sys/vfs_offset.h"
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 79e70f6ef13abddcf4fbd2f25395250ef4626bce..8cd1f5e6ac97229df3df7847bd4a178b8377c9f3 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -140,6 +140,10 @@ VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_o
 }
 
 NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
+    if (file == nullptr) {
+        status = Loader::ResultStatus::ErrorInvalidFormat;
+        return;
+    }
     if (sizeof(NCAHeader) != file->ReadObject(&header))
         LOG_ERROR(Loader, "File reader errored out during header read.");
 
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 6492163b53318d28ac0c9b528078eef9b33cc65c..a984a4d3613122a6f3dea55fc59f71cd988ed659 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -12,6 +12,7 @@
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
+#include "control_metadata.h"
 #include "core/crypto/key_manager.h"
 #include "core/file_sys/partition_filesystem.h"
 #include "core/loader/loader.h"
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 443bc1202494b4d3d66826df222d30774cf58f2c..7f7d8ea0ba4891b8deb2e584bc0ce8f259a43626 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -35,8 +35,6 @@ public:
     ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
     ResultStatus ReadProgramId(u64& out_program_id) override;
 
-    ResultStatus ReadProgramId(u64& out_program_id) override;
-
     ~AppLoader_NCA();
 
 private:
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index eb4dee2c259a4adc117cb04df2ee9cb9cc05cdaf..d3fe24419ac9a4783428fc44fe557e63d7519a43 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -26,7 +26,25 @@ namespace Loader {
 AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
     : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
       nca_loader(std::make_unique<AppLoader_NCA>(
-          xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {}
+          xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {
+    if (xci->GetStatus() != ResultStatus::Success)
+        return;
+    const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
+    if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
+        return;
+    const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
+    if (romfs == nullptr)
+        return;
+    for (const auto& language : FileSys::LANGUAGE_NAMES) {
+        icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
+        if (icon_file != nullptr)
+            break;
+    }
+    const auto nacp_raw = romfs->GetFile("control.nacp");
+    if (nacp_raw == nullptr)
+        return;
+    nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
+}
 
 AppLoader_XCI::~AppLoader_XCI() = default;
 
@@ -71,4 +89,17 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
     return nca_loader->ReadProgramId(out_program_id);
 }
 
+ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
+    if (icon_file == nullptr)
+        return ResultStatus::ErrorInvalidFormat;
+    buffer = icon_file->ReadAllBytes();
+    return ResultStatus::Success;
+}
+
+ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
+    if (nacp_file == nullptr)
+        return ResultStatus::ErrorInvalidFormat;
+    title = nacp_file->GetApplicationName();
+    return ResultStatus::Success;
+}
 } // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 0dbcfbdf83d74bc0d2f37268a62dc2287c9f36c0..973833050e5c1c3972b1626edfa9c66aea7a8918 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -33,12 +33,17 @@ public:
 
     ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
     ResultStatus ReadProgramId(u64& out_program_id) override;
+    ResultStatus ReadIcon(std::vector<u8>& buffer) override;
+    ResultStatus ReadTitle(std::string& title) override;
 
 private:
     FileSys::ProgramMetadata metadata;
 
     std::unique_ptr<FileSys::XCI> xci;
     std::unique_ptr<AppLoader_NCA> nca_loader;
+
+    FileSys::VirtualFile icon_file;
+    std::shared_ptr<FileSys::NACP> nacp_file;
 };
 
 } // namespace Loader
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 481d91be58349c0c2ee7f81e62f12d6ecbf6df48..5f47f5a2ba7887dd05ea830dc9ae3c72d9c5b12e 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -9,6 +9,7 @@
 #include <QKeyEvent>
 #include <QMenu>
 #include <QThreadPool>
+#include <boost/container/flat_map.hpp>
 #include "common/common_paths.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
@@ -458,9 +459,9 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
                 // Use from metadata pool.
                 if (nca_control_map.find(program_id) != nca_control_map.end()) {
                     const auto nca = nca_control_map[program_id];
-                    auto control_dir = nca->GetSection(0);
+                    const auto control_dir = nca->GetSubdirectories()[0];
 
-                    auto nacp_file = control_dir->GetFile("control.nacp");
+                    const auto nacp_file = control_dir->GetFile("control.nacp");
                     FileSys::NACP nacp(nacp_file);
                     name = nacp.GetApplicationName();