summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-09-03 18:57:52 -0400
committerGravatar Zach Hilman2018-09-04 16:25:10 -0400
commit23a16c1720ee522f6ac7d1f426a2d4a918ce41c9 (patch)
tree43a69cb7046a768760e5ae20eddfe3b53d3ca7f8 /src
parentnsp: Fix error masking issue with XCI files (diff)
downloadyuzu-23a16c1720ee522f6ac7d1f426a2d4a918ce41c9.tar.gz
yuzu-23a16c1720ee522f6ac7d1f426a2d4a918ce41c9.tar.xz
yuzu-23a16c1720ee522f6ac7d1f426a2d4a918ce41c9.zip
patch_manager: Centralize Control-type NCA parsing
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/patch_manager.cpp75
-rw-r--r--src/core/file_sys/patch_manager.h13
-rw-r--r--src/core/loader/nsp.cpp20
-rw-r--r--src/core/loader/xci.cpp21
-rw-r--r--src/yuzu/game_list.cpp28
-rw-r--r--src/yuzu/main.cpp12
6 files changed, 89 insertions, 80 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index b6e25f7eb..fa2fbe5e1 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/file_sys/control_metadata.h"
5#include "core/file_sys/patch_manager.h" 6#include "core/file_sys/patch_manager.h"
6#include "core/file_sys/registered_cache.h" 7#include "core/file_sys/registered_cache.h"
7#include "core/hle/service/filesystem/filesystem.h" 8#include "core/hle/service/filesystem/filesystem.h"
@@ -87,29 +88,63 @@ std::map<PatchType, std::string> PatchManager::GetPatchVersionNames() const {
87 const auto installed = Service::FileSystem::GetUnionContents(); 88 const auto installed = Service::FileSystem::GetUnionContents();
88 89
89 const auto update_tid = GetUpdateTitleID(title_id); 90 const auto update_tid = GetUpdateTitleID(title_id);
90 const auto update_control = installed->GetEntry(title_id, ContentRecordType::Control); 91 PatchManager update{update_tid};
91 if (update_control != nullptr) { 92 auto [nacp, discard_icon_file] = update.GetControlMetadata();
92 do { 93
93 const auto romfs = 94 if (nacp != nullptr) {
94 PatchRomFS(update_control->GetRomFS(), update_control->GetBaseIVFCOffset(), 95 out[PatchType::Update] = nacp->GetVersionString();
95 FileSys::ContentRecordType::Control); 96 } else {
96 if (romfs == nullptr) 97 if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
97 break; 98 const auto meta_ver = installed->GetEntryVersion(update_tid);
98 99 if (meta_ver == boost::none || meta_ver.get() == 0) {
99 const auto control_dir = FileSys::ExtractRomFS(romfs); 100 out[PatchType::Update] = "";
100 if (control_dir == nullptr) 101 } else {
101 break; 102 out[PatchType::Update] =
102 103 FormatTitleVersion(meta_ver.get(), TitleVersionFormat::ThreeElements);
103 const auto nacp_file = control_dir->GetFile("control.nacp"); 104 }
104 if (nacp_file == nullptr) 105 }
105 break;
106
107 FileSys::NACP nacp(nacp_file);
108 out[PatchType::Update] = nacp.GetVersionString();
109 } while (false);
110 } 106 }
111 107
112 return out; 108 return out;
113} 109}
114 110
111std::pair<std::shared_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
112 const auto& installed{Service::FileSystem::GetUnionContents()};
113
114 const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control);
115 if (base_control_nca == nullptr)
116 return {};
117
118 return ParseControlNCA(base_control_nca);
119}
120
121std::pair<std::shared_ptr<NACP>, VirtualFile> PatchManager::ParseControlNCA(
122 const std::shared_ptr<NCA>& nca) const {
123 const auto base_romfs = nca->GetRomFS();
124 if (base_romfs == nullptr)
125 return {};
126
127 const auto romfs = PatchRomFS(base_romfs, nca->GetBaseIVFCOffset(), ContentRecordType::Control);
128 if (romfs == nullptr)
129 return {};
130
131 const auto extracted = ExtractRomFS(romfs);
132 if (extracted == nullptr)
133 return {};
134
135 auto nacp_file = extracted->GetFile("control.nacp");
136 if (nacp_file == nullptr)
137 nacp_file = extracted->GetFile("Control.nacp");
138
139 const auto nacp = nacp_file == nullptr ? nullptr : std::make_shared<NACP>(nacp_file);
140
141 VirtualFile icon_file;
142 for (const auto& language : FileSys::LANGUAGE_NAMES) {
143 icon_file = extracted->GetFile("icon_" + std::string(language) + ".dat");
144 if (icon_file != nullptr)
145 break;
146 }
147
148 return {nacp, icon_file};
149}
115} // namespace FileSys 150} // namespace FileSys
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h
index b6bf86222..c2626bc6c 100644
--- a/src/core/file_sys/patch_manager.h
+++ b/src/core/file_sys/patch_manager.h
@@ -7,13 +7,14 @@
7#include <map> 7#include <map>
8#include <string> 8#include <string>
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/file_sys/nca_metadata.h"
11#include "core/file_sys/romfs_factory.h"
10#include "core/file_sys/vfs.h" 12#include "core/file_sys/vfs.h"
11#include "nca_metadata.h"
12#include "romfs_factory.h"
13 13
14namespace FileSys { 14namespace FileSys {
15 15
16class NCA; 16class NCA;
17class NACP;
17 18
18enum class TitleVersionFormat : u8 { 19enum class TitleVersionFormat : u8 {
19 ThreeElements, ///< vX.Y.Z 20 ThreeElements, ///< vX.Y.Z
@@ -47,6 +48,14 @@ public:
47 // i.e. Update v80 will return {Update, 80} 48 // i.e. Update v80 will return {Update, 80}
48 std::map<PatchType, std::string> GetPatchVersionNames() const; 49 std::map<PatchType, std::string> GetPatchVersionNames() const;
49 50
51 // Given title_id of the program, attempts to get the control data of the update and parse it,
52 // falling back to the base control data.
53 std::pair<std::shared_ptr<NACP>, VirtualFile> GetControlMetadata() const;
54
55 // Version of GetControlMetadata that takes an arbitrary NCA
56 std::pair<std::shared_ptr<NACP>, VirtualFile> ParseControlNCA(
57 const std::shared_ptr<NCA>& nca) const;
58
50private: 59private:
51 u64 title_id; 60 u64 title_id;
52}; 61};
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 7c06239f2..291a9876d 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -9,6 +9,8 @@
9#include "core/file_sys/content_archive.h" 9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/control_metadata.h" 10#include "core/file_sys/control_metadata.h"
11#include "core/file_sys/nca_metadata.h" 11#include "core/file_sys/nca_metadata.h"
12#include "core/file_sys/patch_manager.h"
13#include "core/file_sys/registered_cache.h"
12#include "core/file_sys/romfs.h" 14#include "core/file_sys/romfs.h"
13#include "core/file_sys/submission_package.h" 15#include "core/file_sys/submission_package.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
@@ -28,24 +30,12 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
28 return; 30 return;
29 31
30 const auto control_nca = 32 const auto control_nca =
31 nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control); 33 nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
32 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 34 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
33 return; 35 return;
34 36
35 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); 37 std::tie(nacp_file, icon_file) =
36 if (romfs == nullptr) 38 FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(control_nca);
37 return;
38
39 for (const auto& language : FileSys::LANGUAGE_NAMES) {
40 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
41 if (icon_file != nullptr)
42 break;
43 }
44
45 const auto nacp_raw = romfs->GetFile("control.nacp");
46 if (nacp_raw == nullptr)
47 return;
48 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
49} 39}
50 40
51AppLoader_NSP::~AppLoader_NSP() = default; 41AppLoader_NSP::~AppLoader_NSP() = default;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index b01d51abb..16509229f 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -10,6 +10,7 @@
10#include "core/file_sys/control_metadata.h" 10#include "core/file_sys/control_metadata.h"
11#include "core/file_sys/patch_manager.h" 11#include "core/file_sys/patch_manager.h"
12#include "core/file_sys/romfs.h" 12#include "core/file_sys/romfs.h"
13#include "core/file_sys/submission_package.h"
13#include "core/hle/kernel/process.h" 14#include "core/hle/kernel/process.h"
14#include "core/loader/nca.h" 15#include "core/loader/nca.h"
15#include "core/loader/xci.h" 16#include "core/loader/xci.h"
@@ -23,27 +24,11 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
23 return; 24 return;
24 25
25 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); 26 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
26
27 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 27 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
28 return; 28 return;
29 29
30 auto romfs_raw = control_nca->GetRomFS(); 30 std::tie(nacp_file, icon_file) =
31 FileSys::PatchManager patch{xci->GetNCAByType(FileSys::NCAContentType::Program)->GetTitleId()}; 31 FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(control_nca);
32 romfs_raw = patch.PatchRomFS(romfs_raw, control_nca->GetBaseIVFCOffset(),
33 FileSys::ContentRecordType::Control);
34
35 const auto romfs = FileSys::ExtractRomFS(romfs_raw);
36 if (romfs == nullptr)
37 return;
38 for (const auto& language : FileSys::LANGUAGE_NAMES) {
39 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
40 if (icon_file != nullptr)
41 break;
42 }
43 const auto nacp_raw = romfs->GetFile("control.nacp");
44 if (nacp_raw == nullptr)
45 return;
46 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
47} 32}
48 33
49AppLoader_XCI::~AppLoader_XCI() = default; 34AppLoader_XCI::~AppLoader_XCI() = default;
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 38c5071e3..a3b841684 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -486,29 +486,11 @@ void GameList::RefreshGameDirectory() {
486static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, 486static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager,
487 const std::shared_ptr<FileSys::NCA>& nca, 487 const std::shared_ptr<FileSys::NCA>& nca,
488 std::vector<u8>& icon, std::string& name) { 488 std::vector<u8>& icon, std::string& name) {
489 const auto romfs = patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), 489 auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca);
490 FileSys::ContentRecordType::Control); 490 if (icon_file != nullptr)
491 if (romfs == nullptr) 491 icon = icon_file->ReadAllBytes();
492 return; 492 if (nacp != nullptr)
493 493 name = nacp->GetApplicationName();
494 const auto control_dir = FileSys::ExtractRomFS(romfs);
495 if (control_dir == nullptr)
496 return;
497
498 const auto nacp_file = control_dir->GetFile("control.nacp");
499 if (nacp_file == nullptr)
500 return;
501 FileSys::NACP nacp(nacp_file);
502 name = nacp.GetApplicationName();
503
504 FileSys::VirtualFile icon_file = nullptr;
505 for (const auto& language : FileSys::LANGUAGE_NAMES) {
506 icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat");
507 if (icon_file != nullptr) {
508 icon = icon_file->ReadAllBytes();
509 break;
510 }
511 }
512} 494}
513 495
514GameListWorker::GameListWorker( 496GameListWorker::GameListWorker(
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b7ce0248b..80a284513 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -592,8 +592,16 @@ void GMainWindow::BootGame(const QString& filename) {
592 592
593 std::string title_name; 593 std::string title_name;
594 const auto res = Core::System::GetInstance().GetGameName(title_name); 594 const auto res = Core::System::GetInstance().GetGameName(title_name);
595 if (res != Loader::ResultStatus::Success) 595 if (res != Loader::ResultStatus::Success) {
596 title_name = FileUtil::GetFilename(filename.toStdString()); 596 const u64 program_id = Core::System::GetInstance().CurrentProcess()->program_id;
597
598 const auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata();
599 if (nacp != nullptr)
600 title_name = nacp->GetApplicationName();
601
602 if (title_name.empty())
603 title_name = FileUtil::GetFilename(filename.toStdString());
604 }
597 605
598 setWindowTitle(QString("yuzu %1| %4 | %2-%3") 606 setWindowTitle(QString("yuzu %1| %4 | %2-%3")
599 .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc, 607 .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc,