From c91b60a421a3bd0dc85d80e0a5a2d261370df340 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Sat, 1 Sep 2018 13:11:30 -0400
Subject: [PATCH] game_list: Fix version display on non-NAND titles

---
 src/core/file_sys/patch_manager.cpp | 28 +++++++++++++++-----
 src/core/file_sys/patch_manager.h   |  2 +-
 src/core/loader/xci.cpp             | 11 +++++++-
 src/yuzu/game_list.cpp              | 41 +++++++++++++----------------
 4 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 8b7d797734..b6e25f7eb1 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -82,15 +82,31 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset,
     return romfs;
 }
 
-std::map<PatchType, u32> PatchManager::GetPatchVersionNames() const {
-    std::map<PatchType, u32> out;
+std::map<PatchType, std::string> PatchManager::GetPatchVersionNames() const {
+    std::map<PatchType, std::string> out;
     const auto installed = Service::FileSystem::GetUnionContents();
 
     const auto update_tid = GetUpdateTitleID(title_id);
-    const auto update_version = installed->GetEntryVersion(update_tid);
-    if (update_version != boost::none &&
-        installed->HasEntry(update_tid, ContentRecordType::Program)) {
-        out[PatchType::Update] = update_version.get();
+    const auto update_control = installed->GetEntry(title_id, ContentRecordType::Control);
+    if (update_control != nullptr) {
+        do {
+            const auto romfs =
+                PatchRomFS(update_control->GetRomFS(), update_control->GetBaseIVFCOffset(),
+                           FileSys::ContentRecordType::Control);
+            if (romfs == nullptr)
+                break;
+
+            const auto control_dir = FileSys::ExtractRomFS(romfs);
+            if (control_dir == nullptr)
+                break;
+
+            const auto nacp_file = control_dir->GetFile("control.nacp");
+            if (nacp_file == nullptr)
+                break;
+
+            FileSys::NACP nacp(nacp_file);
+            out[PatchType::Update] = nacp.GetVersionString();
+        } while (false);
     }
 
     return out;
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h
index 021bc33667..b6bf86222b 100644
--- a/src/core/file_sys/patch_manager.h
+++ b/src/core/file_sys/patch_manager.h
@@ -45,7 +45,7 @@ public:
 
     // Returns a vector of pairs between patch names and patch versions.
     // i.e. Update v80 will return {Update, 80}
-    std::map<PatchType, u32> GetPatchVersionNames() const;
+    std::map<PatchType, std::string> GetPatchVersionNames() const;
 
 private:
     u64 title_id;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 75b998faaa..b01d51abb7 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -8,6 +8,7 @@
 #include "core/file_sys/card_image.h"
 #include "core/file_sys/content_archive.h"
 #include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
 #include "core/file_sys/romfs.h"
 #include "core/hle/kernel/process.h"
 #include "core/loader/nca.h"
@@ -20,10 +21,18 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
       nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
     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());
+
+    auto romfs_raw = control_nca->GetRomFS();
+    FileSys::PatchManager patch{xci->GetNCAByType(FileSys::NCAContentType::Program)->GetTitleId()};
+    romfs_raw = patch.PatchRomFS(romfs_raw, control_nca->GetBaseIVFCOffset(),
+                                 FileSys::ContentRecordType::Control);
+
+    const auto romfs = FileSys::ExtractRomFS(romfs_raw);
     if (romfs == nullptr)
         return;
     for (const auto& language : FileSys::LANGUAGE_NAMES) {
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 02d8a38828..38c5071e3a 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -457,23 +457,17 @@ static QString FormatGameName(const std::string& physical_name) {
 }
 
 static QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager,
-                                       std::string update_version_override = "",
                                        bool updatable = true) {
     QString out;
     for (const auto& kv : patch_manager.GetPatchVersionNames()) {
         if (!updatable && kv.first == FileSys::PatchType::Update)
             continue;
 
-        if (kv.second == 0) {
+        if (kv.second.empty()) {
             out.append(fmt::format("{}\n", FileSys::FormatPatchTypeName(kv.first)).c_str());
         } else {
-            auto version_data = FileSys::FormatTitleVersion(kv.second);
-            if (kv.first == FileSys::PatchType::Update && !update_version_override.empty())
-                version_data = update_version_override;
-
-            out.append(
-                fmt::format("{} ({})\n", FileSys::FormatPatchTypeName(kv.first), version_data)
-                    .c_str());
+            out.append(fmt::format("{} ({})\n", FileSys::FormatPatchTypeName(kv.first), kv.second)
+                           .c_str());
         }
     }
 
@@ -491,8 +485,7 @@ void GameList::RefreshGameDirectory() {
 
 static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager,
                                       const std::shared_ptr<FileSys::NCA>& nca,
-                                      std::vector<u8>& icon, std::string& name,
-                                      std::string& version) {
+                                      std::vector<u8>& icon, std::string& name) {
     const auto romfs = patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(),
                                                 FileSys::ContentRecordType::Control);
     if (romfs == nullptr)
@@ -507,7 +500,6 @@ static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager
         return;
     FileSys::NACP nacp(nacp_file);
     name = nacp.GetApplicationName();
-    version = nacp.GetVersionString();
 
     FileSys::VirtualFile icon_file = nullptr;
     for (const auto& language : FileSys::LANGUAGE_NAMES) {
@@ -527,7 +519,8 @@ GameListWorker::GameListWorker(
 
 GameListWorker::~GameListWorker() = default;
 
-void GameListWorker::AddInstalledTitlesToGameList(std::shared_ptr<FileSys::RegisteredCache> cache) {
+void GameListWorker::AddInstalledTitlesToGameList() {
+    const auto cache = Service::FileSystem::GetUnionContents();
     const auto installed_games = cache->ListEntriesFilter(FileSys::TitleType::Application,
                                                           FileSys::ContentRecordType::Program);
 
@@ -539,20 +532,28 @@ void GameListWorker::AddInstalledTitlesToGameList(std::shared_ptr<FileSys::Regis
 
         std::vector<u8> icon;
         std::string name;
-        std::string version = "";
         u64 program_id = 0;
         loader->ReadProgramId(program_id);
 
         const FileSys::PatchManager patch{program_id};
         const auto& control = cache->GetEntry(game.title_id, FileSys::ContentRecordType::Control);
         if (control != nullptr)
-            GetMetadataFromControlNCA(patch, control, icon, name, version);
+            GetMetadataFromControlNCA(patch, control, icon, name);
+
+        auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
+
+        // The game list uses this as compatibility number for untested games
+        QString compatibility("99");
+        if (it != compatibility_list.end())
+            compatibility = it->second.first;
+
         emit EntryReady({
             new GameListItemPath(
                 FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name),
                 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
                 program_id),
-            new GameListItem(FormatPatchNameVersions(patch, version)),
+            new GameListItemCompat(compatibility),
+            new GameListItem(FormatPatchNameVersions(patch)),
             new GameListItem(
                 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
             new GameListItemSize(file->GetSize()),
@@ -620,14 +621,12 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
 
             const FileSys::PatchManager patch{program_id};
 
-            std::string version = "";
-
             if (res1 != Loader::ResultStatus::Success && res3 != Loader::ResultStatus::Success &&
                 res2 == Loader::ResultStatus::Success) {
                 // Use from metadata pool.
                 if (nca_control_map.find(program_id) != nca_control_map.end()) {
                     const auto nca = nca_control_map[program_id];
-                    GetMetadataFromControlNCA(patch, nca, icon, name, version);
+                    GetMetadataFromControlNCA(patch, nca, icon, name);
                 }
             }
 
@@ -644,9 +643,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
                     QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
                     program_id),
                 new GameListItemCompat(compatibility),
-                new GameListItem(FormatPatchNameVersions(program_id, loader->IsRomFSUpdatable())),
-                new GameListItem(
-                    FormatPatchNameVersions(patch, version, loader->IsRomFSUpdatable())),
+                new GameListItem(FormatPatchNameVersions(patch, loader->IsRomFSUpdatable())),
                 new GameListItem(
                     QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
                 new GameListItemSize(FileUtil::GetSize(physical_name)),
-- 
GitLab