mirror of https://git.suyu.dev/suyu/suyu
patch_manager: Centralize Control-type NCA parsing
This commit is contained in:
parent
92e26df00f
commit
23a16c1720
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
@ -87,29 +88,63 @@ std::map<PatchType, std::string> PatchManager::GetPatchVersionNames() const {
|
||||||
const auto installed = Service::FileSystem::GetUnionContents();
|
const auto installed = Service::FileSystem::GetUnionContents();
|
||||||
|
|
||||||
const auto update_tid = GetUpdateTitleID(title_id);
|
const auto update_tid = GetUpdateTitleID(title_id);
|
||||||
const auto update_control = installed->GetEntry(title_id, ContentRecordType::Control);
|
PatchManager update{update_tid};
|
||||||
if (update_control != nullptr) {
|
auto [nacp, discard_icon_file] = update.GetControlMetadata();
|
||||||
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 (nacp != nullptr) {
|
||||||
if (control_dir == nullptr)
|
out[PatchType::Update] = nacp->GetVersionString();
|
||||||
break;
|
} else {
|
||||||
|
if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
|
||||||
const auto nacp_file = control_dir->GetFile("control.nacp");
|
const auto meta_ver = installed->GetEntryVersion(update_tid);
|
||||||
if (nacp_file == nullptr)
|
if (meta_ver == boost::none || meta_ver.get() == 0) {
|
||||||
break;
|
out[PatchType::Update] = "";
|
||||||
|
} else {
|
||||||
FileSys::NACP nacp(nacp_file);
|
out[PatchType::Update] =
|
||||||
out[PatchType::Update] = nacp.GetVersionString();
|
FormatTitleVersion(meta_ver.get(), TitleVersionFormat::ThreeElements);
|
||||||
} while (false);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<std::shared_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
|
||||||
|
const auto& installed{Service::FileSystem::GetUnionContents()};
|
||||||
|
|
||||||
|
const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control);
|
||||||
|
if (base_control_nca == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return ParseControlNCA(base_control_nca);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::shared_ptr<NACP>, VirtualFile> PatchManager::ParseControlNCA(
|
||||||
|
const std::shared_ptr<NCA>& nca) const {
|
||||||
|
const auto base_romfs = nca->GetRomFS();
|
||||||
|
if (base_romfs == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto romfs = PatchRomFS(base_romfs, nca->GetBaseIVFCOffset(), ContentRecordType::Control);
|
||||||
|
if (romfs == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto extracted = ExtractRomFS(romfs);
|
||||||
|
if (extracted == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto nacp_file = extracted->GetFile("control.nacp");
|
||||||
|
if (nacp_file == nullptr)
|
||||||
|
nacp_file = extracted->GetFile("Control.nacp");
|
||||||
|
|
||||||
|
const auto nacp = nacp_file == nullptr ? nullptr : std::make_shared<NACP>(nacp_file);
|
||||||
|
|
||||||
|
VirtualFile icon_file;
|
||||||
|
for (const auto& language : FileSys::LANGUAGE_NAMES) {
|
||||||
|
icon_file = extracted->GetFile("icon_" + std::string(language) + ".dat");
|
||||||
|
if (icon_file != nullptr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {nacp, icon_file};
|
||||||
|
}
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "core/file_sys/nca_metadata.h"
|
||||||
|
#include "core/file_sys/romfs_factory.h"
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
#include "nca_metadata.h"
|
|
||||||
#include "romfs_factory.h"
|
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
class NCA;
|
class NCA;
|
||||||
|
class NACP;
|
||||||
|
|
||||||
enum class TitleVersionFormat : u8 {
|
enum class TitleVersionFormat : u8 {
|
||||||
ThreeElements, ///< vX.Y.Z
|
ThreeElements, ///< vX.Y.Z
|
||||||
|
@ -47,6 +48,14 @@ public:
|
||||||
// i.e. Update v80 will return {Update, 80}
|
// i.e. Update v80 will return {Update, 80}
|
||||||
std::map<PatchType, std::string> GetPatchVersionNames() const;
|
std::map<PatchType, std::string> GetPatchVersionNames() const;
|
||||||
|
|
||||||
|
// Given title_id of the program, attempts to get the control data of the update and parse it,
|
||||||
|
// falling back to the base control data.
|
||||||
|
std::pair<std::shared_ptr<NACP>, VirtualFile> GetControlMetadata() const;
|
||||||
|
|
||||||
|
// Version of GetControlMetadata that takes an arbitrary NCA
|
||||||
|
std::pair<std::shared_ptr<NACP>, VirtualFile> ParseControlNCA(
|
||||||
|
const std::shared_ptr<NCA>& nca) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
#include "core/file_sys/romfs.h"
|
#include "core/file_sys/romfs.h"
|
||||||
#include "core/file_sys/submission_package.h"
|
#include "core/file_sys/submission_package.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
@ -28,24 +30,12 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto control_nca =
|
const auto control_nca =
|
||||||
nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control);
|
nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
|
||||||
if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
|
if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
|
std::tie(nacp_file, icon_file) =
|
||||||
if (romfs == nullptr)
|
FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(control_nca);
|
||||||
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_NSP::~AppLoader_NSP() = default;
|
AppLoader_NSP::~AppLoader_NSP() = default;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/file_sys/romfs.h"
|
#include "core/file_sys/romfs.h"
|
||||||
|
#include "core/file_sys/submission_package.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/loader/nca.h"
|
#include "core/loader/nca.h"
|
||||||
#include "core/loader/xci.h"
|
#include "core/loader/xci.h"
|
||||||
|
@ -23,27 +24,11 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
|
const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
|
||||||
|
|
||||||
if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
|
if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto romfs_raw = control_nca->GetRomFS();
|
std::tie(nacp_file, icon_file) =
|
||||||
FileSys::PatchManager patch{xci->GetNCAByType(FileSys::NCAContentType::Program)->GetTitleId()};
|
FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(control_nca);
|
||||||
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) {
|
|
||||||
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;
|
AppLoader_XCI::~AppLoader_XCI() = default;
|
||||||
|
|
|
@ -486,29 +486,11 @@ void GameList::RefreshGameDirectory() {
|
||||||
static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager,
|
static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager,
|
||||||
const std::shared_ptr<FileSys::NCA>& nca,
|
const std::shared_ptr<FileSys::NCA>& nca,
|
||||||
std::vector<u8>& icon, std::string& name) {
|
std::vector<u8>& icon, std::string& name) {
|
||||||
const auto romfs = patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(),
|
auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca);
|
||||||
FileSys::ContentRecordType::Control);
|
if (icon_file != nullptr)
|
||||||
if (romfs == nullptr)
|
icon = icon_file->ReadAllBytes();
|
||||||
return;
|
if (nacp != nullptr)
|
||||||
|
name = nacp->GetApplicationName();
|
||||||
const auto control_dir = FileSys::ExtractRomFS(romfs);
|
|
||||||
if (control_dir == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto nacp_file = control_dir->GetFile("control.nacp");
|
|
||||||
if (nacp_file == nullptr)
|
|
||||||
return;
|
|
||||||
FileSys::NACP nacp(nacp_file);
|
|
||||||
name = nacp.GetApplicationName();
|
|
||||||
|
|
||||||
FileSys::VirtualFile icon_file = nullptr;
|
|
||||||
for (const auto& language : FileSys::LANGUAGE_NAMES) {
|
|
||||||
icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat");
|
|
||||||
if (icon_file != nullptr) {
|
|
||||||
icon = icon_file->ReadAllBytes();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameListWorker::GameListWorker(
|
GameListWorker::GameListWorker(
|
||||||
|
|
|
@ -592,8 +592,16 @@ void GMainWindow::BootGame(const QString& filename) {
|
||||||
|
|
||||||
std::string title_name;
|
std::string title_name;
|
||||||
const auto res = Core::System::GetInstance().GetGameName(title_name);
|
const auto res = Core::System::GetInstance().GetGameName(title_name);
|
||||||
if (res != Loader::ResultStatus::Success)
|
if (res != Loader::ResultStatus::Success) {
|
||||||
title_name = FileUtil::GetFilename(filename.toStdString());
|
const u64 program_id = Core::System::GetInstance().CurrentProcess()->program_id;
|
||||||
|
|
||||||
|
const auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata();
|
||||||
|
if (nacp != nullptr)
|
||||||
|
title_name = nacp->GetApplicationName();
|
||||||
|
|
||||||
|
if (title_name.empty())
|
||||||
|
title_name = FileUtil::GetFilename(filename.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
setWindowTitle(QString("yuzu %1| %4 | %2-%3")
|
setWindowTitle(QString("yuzu %1| %4 | %2-%3")
|
||||||
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc,
|
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc,
|
||||||
|
|
Loading…
Reference in New Issue