forked from eden-emu/eden
		
	Merge pull request #1436 from lioncash/view
submission_package: Cleanup and bug fixes
This commit is contained in:
		
						commit
						3bb12e0e67
					
				
					 2 changed files with 101 additions and 73 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bunnei
						bunnei