diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/file_sys/card_image.cpp | 48 | ||||
-rw-r--r-- | src/core/file_sys/card_image.h | 1 | ||||
-rw-r--r-- | src/core/file_sys/patch_manager.cpp | 9 |
3 files changed, 50 insertions, 8 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 3b2588c84..8b9a4fc5a 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -31,13 +31,9 @@ XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index) : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, partitions(partition_names.size()), partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { - if (file->ReadObject(&header) != sizeof(GamecardHeader)) { - status = Loader::ResultStatus::ErrorBadXCIHeader; - return; - } - - if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) { - status = Loader::ResultStatus::ErrorBadXCIHeader; + const auto header_status = TryReadHeader(); + if (header_status != Loader::ResultStatus::Success) { + status = header_status; return; } @@ -316,6 +312,44 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { return Loader::ResultStatus::Success; } +Loader::ResultStatus XCI::TryReadHeader() { + constexpr size_t CardInitialDataRegionSize = 0x1000; + + // Define the function we'll use to determine if we read a valid header. + const auto ReadCardHeader = [&]() { + // Ensure we can read the entire header. If we can't, we can't read the card image. + if (file->ReadObject(&header) != sizeof(GamecardHeader)) { + return Loader::ResultStatus::ErrorBadXCIHeader; + } + + // Ensure the header magic matches. If it doesn't, this isn't a card image header. + if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) { + return Loader::ResultStatus::ErrorBadXCIHeader; + } + + // We read a card image header. + return Loader::ResultStatus::Success; + }; + + // Try to read the header directly. + if (ReadCardHeader() == Loader::ResultStatus::Success) { + return Loader::ResultStatus::Success; + } + + // Get the size of the file. + const size_t card_image_size = file->GetSize(); + + // If we are large enough to have a key area, offset past the key area and retry. + if (card_image_size >= CardInitialDataRegionSize) { + file = std::make_shared<OffsetVfsFile>(file, card_image_size - CardInitialDataRegionSize, + CardInitialDataRegionSize); + return ReadCardHeader(); + } + + // We had no header and aren't large enough to have a key area, so this can't be parsed. + return Loader::ResultStatus::ErrorBadXCIHeader; +} + u8 XCI::GetFormatVersion() { return GetLogoPartition() == nullptr ? 0x1 : 0x2; } diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 1283f8216..9886123e7 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -128,6 +128,7 @@ public: private: Loader::ResultStatus AddNCAFromPartition(XCIPartition part); + Loader::ResultStatus TryReadHeader(); VirtualFile file; GamecardHeader header{}; diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 0701e3f0e..a4baddb15 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -352,7 +352,8 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t const Service::FileSystem::FileSystemController& fs_controller) { const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); - if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || + if ((type != ContentRecordType::Program && type != ContentRecordType::Data && + type != ContentRecordType::HtmlDocument) || (load_dir == nullptr && sdmc_load_dir == nullptr)) { return; } @@ -381,6 +382,12 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t auto ext_dir = FindSubdirectoryCaseless(subdir, "romfs_ext"); if (ext_dir != nullptr) layers_ext.push_back(std::make_shared<CachedVfsDirectory>(ext_dir)); + + if (type == ContentRecordType::HtmlDocument) { + auto manual_dir = FindSubdirectoryCaseless(subdir, "manual_html"); + if (manual_dir != nullptr) + layers.push_back(std::make_shared<CachedVfsDirectory>(manual_dir)); + } } // When there are no layers to apply, return early as there is no need to rebuild the RomFS |