diff options
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 39 | ||||
| -rw-r--r-- | src/core/file_sys/fsmitm_romfsbuild.cpp | 38 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 3 |
3 files changed, 57 insertions, 23 deletions
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 50303fe42..06efab46d 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -57,11 +57,34 @@ struct NCASectionHeaderBlock { }; static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size."); +struct NCABucketInfo { + u64 table_offset; + u64 table_size; + std::array<u8, 0x10> table_header; +}; +static_assert(sizeof(NCABucketInfo) == 0x20, "NCABucketInfo has incorrect size."); + +struct NCASparseInfo { + NCABucketInfo bucket; + u64 physical_offset; + u16 generation; + INSERT_PADDING_BYTES_NOINIT(0x6); +}; +static_assert(sizeof(NCASparseInfo) == 0x30, "NCASparseInfo has incorrect size."); + +struct NCACompressionInfo { + NCABucketInfo bucket; + INSERT_PADDING_BYTES_NOINIT(0x8); +}; +static_assert(sizeof(NCACompressionInfo) == 0x28, "NCACompressionInfo has incorrect size."); + struct NCASectionRaw { NCASectionHeaderBlock header; std::array<u8, 0x138> block_data; std::array<u8, 0x8> section_ctr; - INSERT_PADDING_BYTES_NOINIT(0xB8); + NCASparseInfo sparse_info; + NCACompressionInfo compression_info; + INSERT_PADDING_BYTES_NOINIT(0x60); }; static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size."); @@ -225,6 +248,20 @@ bool NCA::ReadSections(const std::vector<NCASectionHeader>& sections, u64 bktr_b for (std::size_t i = 0; i < sections.size(); ++i) { const auto& section = sections[i]; + if (section.raw.sparse_info.bucket.table_offset != 0 && + section.raw.sparse_info.bucket.table_size != 0) { + LOG_ERROR(Loader, "Sparse NCAs are not supported."); + status = Loader::ResultStatus::ErrorSparseNCA; + return false; + } + + if (section.raw.compression_info.bucket.table_offset != 0 && + section.raw.compression_info.bucket.table_size != 0) { + LOG_ERROR(Loader, "Compressed NCAs are not supported."); + status = Loader::ResultStatus::ErrorCompressedNCA; + return false; + } + if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) { if (!ReadRomFSSection(section, header.section_tables[i], bktr_base_ivfc_offset)) { return false; diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp index 1ff83c08c..e39c7b62b 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.cpp +++ b/src/core/file_sys/fsmitm_romfsbuild.cpp @@ -105,19 +105,11 @@ static u64 romfs_get_hash_table_count(u64 num_entries) { return count; } -void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir, +void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir, std::shared_ptr<RomFSBuildDirectoryContext> parent) { std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs; - VirtualDir dir; - - if (parent->path_len == 0) { - dir = root_romfs; - } else { - dir = root_romfs->GetDirectoryRelative(parent->path); - } - - const auto entries = dir->GetEntries(); + const auto entries = romfs_dir->GetEntries(); for (const auto& kv : entries) { if (kv.second == VfsEntryType::Directory) { @@ -127,7 +119,7 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); child->path = parent->path + "/" + kv.first; - if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { + if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) { continue; } @@ -144,17 +136,17 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); child->path = parent->path + "/" + kv.first; - if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { + if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) { continue; } // Sanity check on path_len ASSERT(child->path_len < FS_MAX_PATH); - child->source = root_romfs->GetFileRelative(child->path); + child->source = romfs_dir->GetFile(kv.first); if (ext_dir != nullptr) { - if (const auto ips = ext_dir->GetFileRelative(child->path + ".ips")) { + if (const auto ips = ext_dir->GetFile(kv.first + ".ips")) { if (auto patched = PatchIPS(child->source, ips)) { child->source = std::move(patched); } @@ -168,23 +160,27 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir } for (auto& child : child_dirs) { - this->VisitDirectory(root_romfs, ext_dir, child); + auto subdir_name = std::string_view(child->path).substr(child->cur_path_ofs); + auto child_romfs_dir = romfs_dir->GetSubdirectory(subdir_name); + auto child_ext_dir = ext_dir != nullptr ? ext_dir->GetSubdirectory(subdir_name) : nullptr; + this->VisitDirectory(child_romfs_dir, child_ext_dir, child); } } bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, std::shared_ptr<RomFSBuildDirectoryContext> dir_ctx) { // Check whether it's already in the known directories. - const auto existing = directories.find(dir_ctx->path); - if (existing != directories.end()) + const auto [it, is_new] = directories.emplace(dir_ctx->path, nullptr); + if (!is_new) { return false; + } // Add a new directory. num_dirs++; dir_table_size += sizeof(RomFSDirectoryEntry) + Common::AlignUp(dir_ctx->path_len - dir_ctx->cur_path_ofs, 4); dir_ctx->parent = parent_dir_ctx; - directories.emplace(dir_ctx->path, dir_ctx); + it->second = dir_ctx; return true; } @@ -192,8 +188,8 @@ bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, std::shared_ptr<RomFSBuildFileContext> file_ctx) { // Check whether it's already in the known files. - const auto existing = files.find(file_ctx->path); - if (existing != files.end()) { + const auto [it, is_new] = files.emplace(file_ctx->path, nullptr); + if (!is_new) { return false; } @@ -202,7 +198,7 @@ bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> pare file_table_size += sizeof(RomFSFileEntry) + Common::AlignUp(file_ctx->path_len - file_ctx->cur_path_ofs, 4); file_ctx->parent = parent_dir_ctx; - files.emplace(file_ctx->path, file_ctx); + it->second = file_ctx; return true; } diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index b0515ec05..1c706e4d8 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -283,7 +283,8 @@ std::size_t RealVfsFile::GetSize() const { if (size) { return *size; } - return FS::GetSize(path); + auto lk = base.RefreshReference(path, perms, *reference); + return reference->file ? reference->file->GetSize() : 0; } bool RealVfsFile::Resize(std::size_t new_size) { |
