diff options
-rw-r--r-- | src/core/file_sys/program_metadata.cpp | 52 | ||||
-rw-r--r-- | src/core/file_sys/program_metadata.h | 14 |
2 files changed, 51 insertions, 15 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index e0cdf3520..08d489eab 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp @@ -33,11 +33,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) { return Loader::ResultStatus::ErrorBadACIHeader; } - if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) { + // Load acid_file_access per-component instead of the entire struct, since this struct does not + // reflect the layout of the real data. + std::size_t current_offset = acid_header.fac_offset; + if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version, + sizeof(FileAccessControl::version), + current_offset)) { + return Loader::ResultStatus::ErrorBadFileAccessControl; + } + if (sizeof(FileAccessControl::permissions) != + file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions), + current_offset += sizeof(FileAccessControl::version) + 3)) { + return Loader::ResultStatus::ErrorBadFileAccessControl; + } + if (sizeof(FileAccessControl::unknown) != + file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown), + current_offset + sizeof(FileAccessControl::permissions))) { return Loader::ResultStatus::ErrorBadFileAccessControl; } - if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) { + // Load aci_file_access per-component instead of the entire struct, same as acid_file_access + current_offset = aci_header.fah_offset; + if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version, + sizeof(FileAccessHeader::version), + current_offset)) { + return Loader::ResultStatus::ErrorBadFileAccessHeader; + } + if (sizeof(FileAccessHeader::permissions) != + file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions), + current_offset += sizeof(FileAccessHeader::version) + 3)) { + return Loader::ResultStatus::ErrorBadFileAccessHeader; + } + if (sizeof(FileAccessHeader::unk_offset) != + file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset), + current_offset += sizeof(FileAccessHeader::permissions))) { + return Loader::ResultStatus::ErrorBadFileAccessHeader; + } + if (sizeof(FileAccessHeader::unk_size) != + file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size), + current_offset += sizeof(FileAccessHeader::unk_offset))) { + return Loader::ResultStatus::ErrorBadFileAccessHeader; + } + if (sizeof(FileAccessHeader::unk_offset_2) != + file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2), + current_offset += sizeof(FileAccessHeader::unk_size))) { + return Loader::ResultStatus::ErrorBadFileAccessHeader; + } + if (sizeof(FileAccessHeader::unk_size_2) != + file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2), + current_offset + sizeof(FileAccessHeader::unk_offset_2))) { return Loader::ResultStatus::ErrorBadFileAccessHeader; } @@ -152,9 +196,7 @@ void ProgramMetadata::Print() const { LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO"); LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min); LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max); - u64_le permissions_l; // local copy to fix alignment error - std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l)); - LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l); + LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions); // Begin ACI0 printing (actual perms, unsigned) LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data()); diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h index e8fb4e27f..2e8960b07 100644 --- a/src/core/file_sys/program_metadata.h +++ b/src/core/file_sys/program_metadata.h @@ -144,20 +144,18 @@ private: static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); -#pragma pack(push, 1) - + // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not + // reflect the real layout to avoid reference binding to misaligned addresses struct FileAccessControl { u8 version; - INSERT_PADDING_BYTES(3); + // 3 padding bytes u64_le permissions; std::array<u8, 0x20> unknown; }; - static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong"); - struct FileAccessHeader { u8 version; - INSERT_PADDING_BYTES(3); + // 3 padding bytes u64_le permissions; u32_le unk_offset; u32_le unk_size; @@ -165,10 +163,6 @@ private: u32_le unk_size_2; }; - static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong"); - -#pragma pack(pop) - Header npdm_header; AciHeader aci_header; AcidHeader acid_header; |