summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/card_image.cpp48
-rw-r--r--src/core/file_sys/card_image.h1
-rw-r--r--src/core/file_sys/patch_manager.cpp9
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