summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-08-11 15:39:09 -0400
committerGravatar Zach Hilman2018-08-11 22:50:48 -0400
commit893447b6b0f5068f3cc2111b5f21c3cff68002e2 (patch)
treef2451fcb2478243621b6952ca5b006f22f957022 /src
parentnca_metadata: Remove unnecessary reference to base file (diff)
downloadyuzu-893447b6b0f5068f3cc2111b5f21c3cff68002e2.tar.gz
yuzu-893447b6b0f5068f3cc2111b5f21c3cff68002e2.tar.xz
yuzu-893447b6b0f5068f3cc2111b5f21c3cff68002e2.zip
registration: Update documentation and style
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/nca_metadata.cpp63
-rw-r--r--src/core/file_sys/nca_metadata.h7
-rw-r--r--src/core/file_sys/registered_cache.cpp23
-rw-r--r--src/core/file_sys/vfs_concat.cpp1
-rw-r--r--src/core/file_sys/vfs_real.cpp17
5 files changed, 69 insertions, 42 deletions
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp
index 38b5eae80..234d70199 100644
--- a/src/core/file_sys/nca_metadata.cpp
+++ b/src/core/file_sys/nca_metadata.cpp
@@ -4,36 +4,44 @@
4 4
5#include <cstring> 5#include <cstring>
6#include "common/common_funcs.h" 6#include "common/common_funcs.h"
7#include "common/logging/log.h"
7#include "common/swap.h" 8#include "common/swap.h"
8#include "content_archive.h" 9#include "content_archive.h"
9#include "core/file_sys/nca_metadata.h" 10#include "core/file_sys/nca_metadata.h"
10 11
11namespace FileSys { 12namespace FileSys {
12 13
13CNMT::CNMT(VirtualFile file) : header(std::make_unique<CNMTHeader>()) { 14bool operator>=(TitleType lhs, TitleType rhs) {
14 if (file->ReadObject(header.get()) != sizeof(CNMTHeader)) 15 return static_cast<size_t>(lhs) >= static_cast<size_t>(rhs);
16}
17
18bool operator<=(TitleType lhs, TitleType rhs) {
19 return static_cast<size_t>(lhs) <= static_cast<size_t>(rhs);
20}
21
22CNMT::CNMT(VirtualFile file) {
23 if (file->ReadObject(&header) != sizeof(CNMTHeader))
15 return; 24 return;
16 25
17 // If type is {Application, Update, AOC} has opt-header. 26 // If type is {Application, Update, AOC} has opt-header.
18 if (static_cast<u8>(header->type) >= 0x80 && static_cast<u8>(header->type) <= 0x82) { 27 if (header.type >= TitleType::Application && header.type <= TitleType::AOC) {
19 opt_header = std::make_unique<OptionalHeader>(); 28 if (file->ReadObject(&opt_header, sizeof(CNMTHeader)) != sizeof(OptionalHeader)) {
20 if (file->ReadObject(opt_header.get(), sizeof(CNMTHeader)) != sizeof(OptionalHeader)) { 29 LOG_WARNING(Loader, "Failed to read optional header.");
21 opt_header = nullptr;
22 } 30 }
23 } 31 }
24 32
25 for (u16 i = 0; i < header->number_content_entries; ++i) { 33 for (u16 i = 0; i < header.number_content_entries; ++i) {
26 auto& next = content_records.emplace_back(ContentRecord{}); 34 auto& next = content_records.emplace_back(ContentRecord{});
27 if (file->ReadObject(&next, sizeof(CNMTHeader) + i * sizeof(ContentRecord) + 35 if (file->ReadObject(&next, sizeof(CNMTHeader) + i * sizeof(ContentRecord) +
28 header->table_offset) != sizeof(ContentRecord)) { 36 header.table_offset) != sizeof(ContentRecord)) {
29 content_records.erase(content_records.end() - 1); 37 content_records.erase(content_records.end() - 1);
30 } 38 }
31 } 39 }
32 40
33 for (u16 i = 0; i < header->number_meta_entries; ++i) { 41 for (u16 i = 0; i < header.number_meta_entries; ++i) {
34 auto& next = meta_records.emplace_back(MetaRecord{}); 42 auto& next = meta_records.emplace_back(MetaRecord{});
35 if (file->ReadObject(&next, sizeof(CNMTHeader) + i * sizeof(MetaRecord) + 43 if (file->ReadObject(&next, sizeof(CNMTHeader) + i * sizeof(MetaRecord) +
36 header->table_offset) != sizeof(MetaRecord)) { 44 header.table_offset) != sizeof(MetaRecord)) {
37 meta_records.erase(meta_records.end() - 1); 45 meta_records.erase(meta_records.end() - 1);
38 } 46 }
39 } 47 }
@@ -41,20 +49,19 @@ CNMT::CNMT(VirtualFile file) : header(std::make_unique<CNMTHeader>()) {
41 49
42CNMT::CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, 50CNMT::CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records,
43 std::vector<MetaRecord> meta_records) 51 std::vector<MetaRecord> meta_records)
44 : header(std::make_unique<CNMTHeader>(std::move(header))), 52 : header(std::move(header)), opt_header(std::move(opt_header)),
45 opt_header(std::make_unique<OptionalHeader>(std::move(opt_header))),
46 content_records(std::move(content_records)), meta_records(std::move(meta_records)) {} 53 content_records(std::move(content_records)), meta_records(std::move(meta_records)) {}
47 54
48u64 CNMT::GetTitleID() const { 55u64 CNMT::GetTitleID() const {
49 return header->title_id; 56 return header.title_id;
50} 57}
51 58
52u32 CNMT::GetTitleVersion() const { 59u32 CNMT::GetTitleVersion() const {
53 return header->title_version; 60 return header.title_version;
54} 61}
55 62
56TitleType CNMT::GetType() const { 63TitleType CNMT::GetType() const {
57 return header->type; 64 return header.type;
58} 65}
59 66
60const std::vector<ContentRecord>& CNMT::GetContentRecords() const { 67const std::vector<ContentRecord>& CNMT::GetContentRecords() const {
@@ -74,7 +81,7 @@ bool CNMT::UnionRecords(const CNMT& other) {
74 }); 81 });
75 if (iter == content_records.end()) { 82 if (iter == content_records.end()) {
76 content_records.emplace_back(rec); 83 content_records.emplace_back(rec);
77 ++header->number_content_entries; 84 ++header.number_content_entries;
78 change = true; 85 change = true;
79 } 86 }
80 } 87 }
@@ -86,7 +93,7 @@ bool CNMT::UnionRecords(const CNMT& other) {
86 }); 93 });
87 if (iter == meta_records.end()) { 94 if (iter == meta_records.end()) {
88 meta_records.emplace_back(rec); 95 meta_records.emplace_back(rec);
89 ++header->number_meta_entries; 96 ++header.number_meta_entries;
90 change = true; 97 change = true;
91 } 98 }
92 } 99 }
@@ -94,30 +101,30 @@ bool CNMT::UnionRecords(const CNMT& other) {
94} 101}
95 102
96std::vector<u8> CNMT::Serialize() const { 103std::vector<u8> CNMT::Serialize() const {
97 if (header == nullptr) 104 const bool has_opt_header =
98 return {}; 105 header.type >= TitleType::Application && header.type <= TitleType::AOC;
99 std::vector<u8> out(sizeof(CNMTHeader)); 106 std::vector<u8> out(sizeof(CNMTHeader) + (has_opt_header ? sizeof(OptionalHeader) : 0));
100 out.reserve(0x100); // Avoid resizing -- average size. 107 memcpy(out.data(), &header, sizeof(CNMTHeader));
101 memcpy(out.data(), header.get(), sizeof(CNMTHeader)); 108
102 if (opt_header != nullptr) { 109 // Optional Header
103 out.resize(out.size() + sizeof(OptionalHeader)); 110 if (has_opt_header) {
104 memcpy(out.data() + sizeof(CNMTHeader), opt_header.get(), sizeof(OptionalHeader)); 111 memcpy(out.data() + sizeof(CNMTHeader), &opt_header, sizeof(OptionalHeader));
105 } 112 }
106 113
107 auto offset = header->table_offset; 114 auto offset = header.table_offset;
108 115
109 const auto dead_zone = offset + sizeof(CNMTHeader) - out.size(); 116 const auto dead_zone = offset + sizeof(CNMTHeader) - out.size();
110 if (dead_zone > 0) 117 if (dead_zone > 0)
111 out.resize(offset + sizeof(CNMTHeader)); 118 out.resize(offset + sizeof(CNMTHeader));
112 119
120 out.resize(out.size() + content_records.size() * sizeof(ContentRecord));
113 for (const auto& rec : content_records) { 121 for (const auto& rec : content_records) {
114 out.resize(out.size() + sizeof(ContentRecord));
115 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord)); 122 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord));
116 offset += sizeof(ContentRecord); 123 offset += sizeof(ContentRecord);
117 } 124 }
118 125
126 out.resize(out.size() + content_records.size() * sizeof(MetaRecord));
119 for (const auto& rec : meta_records) { 127 for (const auto& rec : meta_records) {
120 out.resize(out.size() + sizeof(MetaRecord));
121 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(MetaRecord)); 128 memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(MetaRecord));
122 offset += sizeof(MetaRecord); 129 offset += sizeof(MetaRecord);
123 } 130 }
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h
index c1ca9b061..88e66d4da 100644
--- a/src/core/file_sys/nca_metadata.h
+++ b/src/core/file_sys/nca_metadata.h
@@ -29,6 +29,9 @@ enum class TitleType : u8 {
29 DeltaTitle = 0x83, 29 DeltaTitle = 0x83,
30}; 30};
31 31
32bool operator>=(TitleType lhs, TitleType rhs);
33bool operator<=(TitleType lhs, TitleType rhs);
34
32enum class ContentRecordType : u8 { 35enum class ContentRecordType : u8 {
33 Meta = 0, 36 Meta = 0,
34 Program = 1, 37 Program = 1,
@@ -96,8 +99,8 @@ public:
96 std::vector<u8> Serialize() const; 99 std::vector<u8> Serialize() const;
97 100
98private: 101private:
99 std::unique_ptr<CNMTHeader> header; 102 CNMTHeader header;
100 std::unique_ptr<OptionalHeader> opt_header; 103 OptionalHeader opt_header;
101 std::vector<ContentRecord> content_records; 104 std::vector<ContentRecord> content_records;
102 std::vector<MetaRecord> meta_records; 105 std::vector<MetaRecord> meta_records;
103 106
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index aaadb7463..20fec2391 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -23,13 +23,14 @@ bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs)
23} 23}
24 24
25static bool FollowsTwoDigitDirFormat(std::string_view name) { 25static bool FollowsTwoDigitDirFormat(std::string_view name) {
26 static const std::regex two_digit_regex( 26 static const std::regex two_digit_regex("000000[0-9A-F]{2}", std::regex_constants::ECMAScript |
27 "000000[0123456789abcdefABCDEF][0123456789abcdefABCDEF]"); 27 std::regex_constants::icase);
28 return std::regex_match(name.begin(), name.end(), two_digit_regex); 28 return std::regex_match(name.begin(), name.end(), two_digit_regex);
29} 29}
30 30
31static bool FollowsNcaIdFormat(std::string_view name) { 31static bool FollowsNcaIdFormat(std::string_view name) {
32 static const std::regex nca_id_regex("[0123456789abcdefABCDEF]+.nca"); 32 static const std::regex nca_id_regex("[0-9A-F]{32}.nca", std::regex_constants::ECMAScript |
33 std::regex_constants::icase);
33 return name.size() == 36 && std::regex_match(name.begin(), name.end(), nca_id_regex); 34 return name.size() == 36 && std::regex_match(name.begin(), name.end(), nca_id_regex);
34} 35}
35 36
@@ -57,8 +58,9 @@ static std::string GetCNMTName(TitleType type, u64 title_id) {
57 }; 58 };
58 59
59 auto index = static_cast<size_t>(type); 60 auto index = static_cast<size_t>(type);
60 if (index >= 0x80) 61 // If the index is after the jump in TitleType, subtract it out.
61 index -= 0x80; 62 if (index >= static_cast<size_t>(TitleType::Application))
63 index -= static_cast<size_t>(TitleType::Application);
62 return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id); 64 return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id);
63} 65}
64 66
@@ -120,9 +122,15 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
120 122
121VirtualFile RegisteredCache::GetFileAtID(NcaID id) const { 123VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
122 VirtualFile file; 124 VirtualFile file;
125 // Try all four modes of file storage:
126 // (bit 1 = uppercase/lower, bit 0 = within a two-digit dir)
127 // 00: /000000**/{:032X}.nca
128 // 01: /{:032X}.nca
129 // 10: /000000**/{:032x}.nca
130 // 11: /{:032x}.nca
123 for (u8 i = 0; i < 4; ++i) { 131 for (u8 i = 0; i < 4; ++i) {
124 file = OpenFileOrDirectoryConcat( 132 const auto path = GetRelativePathFromNcaID(id, (i & 0b10) == 0, (i & 0b01) == 0);
125 dir, GetRelativePathFromNcaID(id, (i & 0b10) == 0, (i & 0b01) == 0)); 133 file = OpenFileOrDirectoryConcat(dir, path);
126 if (file != nullptr) 134 if (file != nullptr)
127 return file; 135 return file;
128 } 136 }
@@ -420,6 +428,7 @@ bool RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunct
420} 428}
421 429
422bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) { 430bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) {
431 // Reasoning behind this method can be found in the comment for InstallEntry, NCA overload.
423 const auto dir = this->dir->CreateDirectoryRelative("yuzu_meta"); 432 const auto dir = this->dir->CreateDirectoryRelative("yuzu_meta");
424 const auto filename = GetCNMTName(cnmt.GetType(), cnmt.GetTitleID()); 433 const auto filename = GetCNMTName(cnmt.GetType(), cnmt.GetTitleID());
425 if (dir->GetFile(filename) == nullptr) { 434 if (dir->GetFile(filename) == nullptr) {
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 88a9a5259..e6bf586a3 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -68,6 +68,7 @@ size_t ConcatenatedVfsFile::Read(u8* data, size_t length, size_t offset) const {
68 } 68 }
69 } 69 }
70 70
71 // Check if the entry should be the last one. The loop above will make it end().
71 if (entry == files.end() && offset < files.rbegin()->first + files.rbegin()->second->GetSize()) 72 if (entry == files.end() && offset < files.rbegin()->first + files.rbegin()->second->GetSize())
72 --entry; 73 --entry;
73 74
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index fa682153c..33ab35fcd 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -83,10 +83,12 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
83 83
84VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { 84VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
85 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); 85 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
86 if (!FileUtil::Exists(path) && 86 if (!FileUtil::Exists(path))
87 !FileUtil::CreateFullPath( 87 return nullptr;
88 FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash)) && 88 if (!FileUtil::CreateFullPath(
89 !FileUtil::CreateEmptyFile(path)) 89 FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash)))
90 return nullptr;
91 if (!FileUtil::CreateEmptyFile(path))
90 return nullptr; 92 return nullptr;
91 return OpenFile(path, perms); 93 return OpenFile(path, perms);
92} 94}
@@ -143,7 +145,12 @@ VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms)
143 145
144VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { 146VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
145 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); 147 const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
146 if (!FileUtil::Exists(path) && !FileUtil::CreateDir(path)) 148 if (!FileUtil::Exists(path))
149 return nullptr;
150 if (!FileUtil::CreateFullPath(
151 FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash)))
152 return nullptr;
153 if (!FileUtil::CreateDir(path))
147 return nullptr; 154 return nullptr;
148 // Cannot use make_shared as RealVfsDirectory constructor is private 155 // Cannot use make_shared as RealVfsDirectory constructor is private
149 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); 156 return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));