1 // Copyright 2017 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <memory> 9 #include <string> 10 #include <vector> 11 #include "common/common_types.h" 12 #include "common/swap.h" 13 #include "core/file_sys/ticket.h" 14 #include "core/file_sys/title_metadata.h" 15 16 namespace Loader { 17 enum class ResultStatus; 18 } 19 20 //////////////////////////////////////////////////////////////////////////////////////////////////// 21 // FileSys namespace 22 23 namespace FileSys { 24 25 class FileBackend; 26 27 constexpr std::size_t CIA_CONTENT_MAX_COUNT = 0x10000; 28 constexpr std::size_t CIA_CONTENT_BITS_SIZE = (CIA_CONTENT_MAX_COUNT / 8); 29 constexpr std::size_t CIA_HEADER_SIZE = 0x2020; 30 constexpr std::size_t CIA_DEPENDENCY_SIZE = 0x300; 31 constexpr std::size_t CIA_METADATA_SIZE = 0x400; 32 33 /** 34 * Helper which implements an interface to read and write CTR Installable Archive (CIA) files. 35 * Data can either be loaded from a FileBackend, a string path, or from a data array. Data can 36 * also be partially loaded for CIAs which are downloading/streamed in and need some metadata 37 * read out. 38 */ 39 class CIAContainer { 40 public: 41 // Load whole CIAs outright 42 Loader::ResultStatus Load(const FileBackend& backend); 43 Loader::ResultStatus Load(const std::string& filepath); 44 Loader::ResultStatus Load(const std::vector<u8>& header_data); 45 46 // Load parts of CIAs (for CIAs streamed in) 47 Loader::ResultStatus LoadHeader(const std::vector<u8>& header_data, std::size_t offset = 0); 48 Loader::ResultStatus LoadTicket(const std::vector<u8>& ticket_data, std::size_t offset = 0); 49 Loader::ResultStatus LoadTitleMetadata(const std::vector<u8>& tmd_data, std::size_t offset = 0); 50 Loader::ResultStatus LoadMetadata(const std::vector<u8>& meta_data, std::size_t offset = 0); 51 52 const Ticket& GetTicket() const; 53 const TitleMetadata& GetTitleMetadata() const; 54 std::array<u64, 0x30>& GetDependencies(); 55 u32 GetCoreVersion() const; 56 57 u64 GetCertificateOffset() const; 58 u64 GetTicketOffset() const; 59 u64 GetTitleMetadataOffset() const; 60 u64 GetMetadataOffset() const; 61 u64 GetContentOffset(std::size_t index = 0) const; 62 63 u32 GetCertificateSize() const; 64 u32 GetTicketSize() const; 65 u32 GetTitleMetadataSize() const; 66 u32 GetMetadataSize() const; 67 u64 GetTotalContentSize() const; 68 u64 GetContentSize(std::size_t index = 0) const; 69 70 void Print() const; 71 72 private: 73 struct Header { 74 u32_le header_size; 75 u16_le type; 76 u16_le version; 77 u32_le cert_size; 78 u32_le tik_size; 79 u32_le tmd_size; 80 u32_le meta_size; 81 u64_le content_size; 82 std::array<u8, CIA_CONTENT_BITS_SIZE> content_present; 83 IsContentPresentHeader84 bool IsContentPresent(std::size_t index) const { 85 // The content_present is a bit array which defines which content in the TMD 86 // is included in the CIA, so check the bit for this index and add if set. 87 // The bits in the content index are arranged w/ index 0 as the MSB, 7 as the LSB, etc. 88 return (content_present[index >> 3] & (0x80 >> (index & 7))) != 0; 89 } 90 }; 91 92 static_assert(sizeof(Header) == CIA_HEADER_SIZE, "CIA Header structure size is wrong"); 93 94 struct Metadata { 95 std::array<u64_le, 0x30> dependencies; 96 std::array<u8, 0x180> reserved; 97 u32_le core_version; 98 std::array<u8, 0xfc> reserved_2; 99 }; 100 101 static_assert(sizeof(Metadata) == CIA_METADATA_SIZE, "CIA Metadata structure size is wrong"); 102 103 Header cia_header; 104 Metadata cia_metadata; 105 Ticket cia_ticket; 106 TitleMetadata cia_tmd; 107 }; 108 109 } // namespace FileSys 110