mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1436 from lioncash/view
submission_package: Cleanup and bug fixes
This commit is contained in:
		
						commit
						15b2e2ec13
					
				@ -18,6 +18,39 @@
 | 
				
			|||||||
#include "core/loader/loader.h"
 | 
					#include "core/loader/loader.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace FileSys {
 | 
					namespace FileSys {
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					void SetTicketKeys(const std::vector<VirtualFile>& files) {
 | 
				
			||||||
 | 
					    Core::Crypto::KeyManager keys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const auto& ticket_file : files) {
 | 
				
			||||||
 | 
					        if (ticket_file == nullptr) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ticket_file->GetExtension() != "tik") {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ticket_file->GetSize() <
 | 
				
			||||||
 | 
					            Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Core::Crypto::Key128 key{};
 | 
				
			||||||
 | 
					        ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We get the name without the extension in order to create the rights ID.
 | 
				
			||||||
 | 
					        std::string name_only(ticket_file->GetName());
 | 
				
			||||||
 | 
					        name_only.erase(name_only.size() - 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
 | 
				
			||||||
 | 
					        u128 rights_id;
 | 
				
			||||||
 | 
					        std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
 | 
				
			||||||
 | 
					        keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // Anonymous namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NSP::NSP(VirtualFile file_)
 | 
					NSP::NSP(VirtualFile file_)
 | 
				
			||||||
    : file(std::move(file_)), status{Loader::ResultStatus::Success},
 | 
					    : file(std::move(file_)), status{Loader::ResultStatus::Success},
 | 
				
			||||||
      pfs(std::make_shared<PartitionFilesystem>(file)) {
 | 
					      pfs(std::make_shared<PartitionFilesystem>(file)) {
 | 
				
			||||||
@ -26,83 +59,16 @@ NSP::NSP(VirtualFile file_)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto files = pfs->GetFiles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (IsDirectoryExeFS(pfs)) {
 | 
					    if (IsDirectoryExeFS(pfs)) {
 | 
				
			||||||
        extracted = true;
 | 
					        extracted = true;
 | 
				
			||||||
        exefs = pfs;
 | 
					        InitializeExeFSAndRomFS(files);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const auto& files = pfs->GetFiles();
 | 
					 | 
				
			||||||
        const auto romfs_iter =
 | 
					 | 
				
			||||||
            std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
 | 
					 | 
				
			||||||
                return file->GetName().find(".romfs") != std::string::npos;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        if (romfs_iter != files.end())
 | 
					 | 
				
			||||||
            romfs = *romfs_iter;
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    extracted = false;
 | 
					    SetTicketKeys(files);
 | 
				
			||||||
    const auto files = pfs->GetFiles();
 | 
					    ReadNCAs(files);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    Core::Crypto::KeyManager keys;
 | 
					 | 
				
			||||||
    for (const auto& ticket_file : files) {
 | 
					 | 
				
			||||||
        if (ticket_file->GetExtension() == "tik") {
 | 
					 | 
				
			||||||
            if (ticket_file == nullptr ||
 | 
					 | 
				
			||||||
                ticket_file->GetSize() <
 | 
					 | 
				
			||||||
                    Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Core::Crypto::Key128 key{};
 | 
					 | 
				
			||||||
            ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
 | 
					 | 
				
			||||||
            std::string_view name_only(ticket_file->GetName());
 | 
					 | 
				
			||||||
            name_only.remove_suffix(4);
 | 
					 | 
				
			||||||
            const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
 | 
					 | 
				
			||||||
            u128 rights_id;
 | 
					 | 
				
			||||||
            std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
 | 
					 | 
				
			||||||
            keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const auto& outer_file : files) {
 | 
					 | 
				
			||||||
        if (outer_file->GetName().substr(outer_file->GetName().size() - 9) == ".cnmt.nca") {
 | 
					 | 
				
			||||||
            const auto nca = std::make_shared<NCA>(outer_file);
 | 
					 | 
				
			||||||
            if (nca->GetStatus() != Loader::ResultStatus::Success) {
 | 
					 | 
				
			||||||
                program_status[nca->GetTitleId()] = nca->GetStatus();
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const auto section0 = nca->GetSubdirectories()[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (const auto& inner_file : section0->GetFiles()) {
 | 
					 | 
				
			||||||
                if (inner_file->GetExtension() != "cnmt")
 | 
					 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                const CNMT cnmt(inner_file);
 | 
					 | 
				
			||||||
                auto& ncas_title = ncas[cnmt.GetTitleID()];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                ncas_title[ContentRecordType::Meta] = nca;
 | 
					 | 
				
			||||||
                for (const auto& rec : cnmt.GetContentRecords()) {
 | 
					 | 
				
			||||||
                    const auto id_string = Common::HexArrayToString(rec.nca_id, false);
 | 
					 | 
				
			||||||
                    const auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
 | 
					 | 
				
			||||||
                    if (next_file == nullptr) {
 | 
					 | 
				
			||||||
                        LOG_WARNING(Service_FS,
 | 
					 | 
				
			||||||
                                    "NCA with ID {}.nca is listed in content metadata, but cannot "
 | 
					 | 
				
			||||||
                                    "be found in PFS. NSP appears to be corrupted.",
 | 
					 | 
				
			||||||
                                    id_string);
 | 
					 | 
				
			||||||
                        continue;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    auto next_nca = std::make_shared<NCA>(next_file);
 | 
					 | 
				
			||||||
                    if (next_nca->GetType() == NCAContentType::Program)
 | 
					 | 
				
			||||||
                        program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
 | 
					 | 
				
			||||||
                    if (next_nca->GetStatus() == Loader::ResultStatus::Success)
 | 
					 | 
				
			||||||
                        ncas_title[rec.type] = std::move(next_nca);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NSP::~NSP() = default;
 | 
					NSP::~NSP() = default;
 | 
				
			||||||
@ -242,4 +208,63 @@ VirtualDir NSP::GetParentDirectory() const {
 | 
				
			|||||||
bool NSP::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
 | 
					bool NSP::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) {
 | 
				
			||||||
 | 
					    exefs = pfs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto romfs_iter = std::find_if(files.begin(), files.end(), [](const VirtualFile& file) {
 | 
				
			||||||
 | 
					        return file->GetName().rfind(".romfs") != std::string::npos;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (romfs_iter == files.end()) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    romfs = *romfs_iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
 | 
				
			||||||
 | 
					    for (const auto& outer_file : files) {
 | 
				
			||||||
 | 
					        if (outer_file->GetName().substr(outer_file->GetName().size() - 9) != ".cnmt.nca") {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto nca = std::make_shared<NCA>(outer_file);
 | 
				
			||||||
 | 
					        if (nca->GetStatus() != Loader::ResultStatus::Success) {
 | 
				
			||||||
 | 
					            program_status[nca->GetTitleId()] = nca->GetStatus();
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto section0 = nca->GetSubdirectories()[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const auto& inner_file : section0->GetFiles()) {
 | 
				
			||||||
 | 
					            if (inner_file->GetExtension() != "cnmt")
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const CNMT cnmt(inner_file);
 | 
				
			||||||
 | 
					            auto& ncas_title = ncas[cnmt.GetTitleID()];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ncas_title[ContentRecordType::Meta] = nca;
 | 
				
			||||||
 | 
					            for (const auto& rec : cnmt.GetContentRecords()) {
 | 
				
			||||||
 | 
					                const auto id_string = Common::HexArrayToString(rec.nca_id, false);
 | 
				
			||||||
 | 
					                const auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
 | 
				
			||||||
 | 
					                if (next_file == nullptr) {
 | 
				
			||||||
 | 
					                    LOG_WARNING(Service_FS,
 | 
				
			||||||
 | 
					                                "NCA with ID {}.nca is listed in content metadata, but cannot "
 | 
				
			||||||
 | 
					                                "be found in PFS. NSP appears to be corrupted.",
 | 
				
			||||||
 | 
					                                id_string);
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto next_nca = std::make_shared<NCA>(next_file);
 | 
				
			||||||
 | 
					                if (next_nca->GetType() == NCAContentType::Program)
 | 
				
			||||||
 | 
					                    program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
 | 
				
			||||||
 | 
					                if (next_nca->GetStatus() == Loader::ResultStatus::Success)
 | 
				
			||||||
 | 
					                    ncas_title[rec.type] = std::move(next_nca);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
} // namespace FileSys
 | 
					} // namespace FileSys
 | 
				
			||||||
 | 
				
			|||||||
@ -59,9 +59,12 @@ protected:
 | 
				
			|||||||
    bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 | 
					    bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					    void InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files);
 | 
				
			||||||
 | 
					    void ReadNCAs(const std::vector<VirtualFile>& files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VirtualFile file;
 | 
					    VirtualFile file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool extracted;
 | 
					    bool extracted = false;
 | 
				
			||||||
    Loader::ResultStatus status;
 | 
					    Loader::ResultStatus status;
 | 
				
			||||||
    std::map<u64, Loader::ResultStatus> program_status;
 | 
					    std::map<u64, Loader::ResultStatus> program_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user