mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 15:57:02 -05:00
178 lines
4.7 KiB
Rust
178 lines
4.7 KiB
Rust
#pragma description ISO 9660 file system
|
|
#pragma MIME application/x-iso9660-image
|
|
|
|
#pragma endian little
|
|
|
|
import std.io;
|
|
import std.mem;
|
|
|
|
enum VolumeDescriptorTypes : u8 {
|
|
BootRecord,
|
|
PrimaryVolume,
|
|
SupplementaryVolume,
|
|
VolumePartition,
|
|
Terminator = 0xff,
|
|
};
|
|
|
|
struct di32 {
|
|
s32 leValue;
|
|
be s32 beValue;
|
|
} [[static]];
|
|
|
|
struct di16 {
|
|
s16 leValue;
|
|
be s16 beValue;
|
|
} [[static]];
|
|
|
|
struct PathTablePtr {
|
|
s32 leMainOffset;
|
|
s32 leOptOffset;
|
|
be s32 beMainOffset;
|
|
be s32 beOptOffset;
|
|
} [[static]];
|
|
|
|
struct DateFormat {
|
|
u8 year;
|
|
u8 month;
|
|
u8 day;
|
|
u8 hour;
|
|
u8 minute;
|
|
u8 second;
|
|
u8 gmtOffset;
|
|
} [[static]];
|
|
|
|
fn FormatDate(DateFormat fmt) {
|
|
s16 gmt = (-48 + fmt.gmtOffset) * 15;
|
|
float gmtHour = gmt / 60;
|
|
s16 gmtMinute = gmt % 60;
|
|
str retVal = std::format("{}.{:02}.{:02} {:02}:{:02}:{:02} GMT{:+03}:{:02}",
|
|
fmt.day, fmt.month, fmt.year + 1900,
|
|
fmt.hour, fmt.minute, fmt.second,
|
|
gmtHour, gmtMinute);
|
|
return retVal;
|
|
};
|
|
|
|
struct StrDateFormat {
|
|
char year[4];
|
|
char month[2];
|
|
char day[2];
|
|
char hour[2];
|
|
char minute[2];
|
|
char second[2];
|
|
char secondFrac[2];
|
|
u8 gmtOffset;
|
|
} [[static]];
|
|
|
|
fn FormatStrDate(StrDateFormat fmt) {
|
|
s16 gmt = (-48 + fmt.gmtOffset) * 15;
|
|
float gmtHour = gmt / 60;
|
|
s16 gmtMinute = gmt % 60;
|
|
str retVal = std::format("{}.{}.{} {}:{}:{}.{} GMT{:+03}:{:02}",
|
|
fmt.day, fmt.month, fmt.year,
|
|
fmt.hour, fmt.minute, fmt.second, fmt.secondFrac,
|
|
gmtHour, gmtMinute);
|
|
return retVal;
|
|
};
|
|
|
|
bitfield FileFlags {
|
|
hidden : 1;
|
|
directory : 1;
|
|
associatedFile : 1;
|
|
extendedAttribute : 1;
|
|
ownerAndGroupInExtendedAttribute : 1;
|
|
padding : 2;
|
|
fileRecordNotFinal : 1;
|
|
};
|
|
|
|
struct DirectoryRecord {
|
|
u8 recordSize;
|
|
u8 extendedRecordSize;
|
|
di32 extentOffset;
|
|
di32 dataSize;
|
|
DateFormat recordDate[[format("FormatDate")]];
|
|
FileFlags fileFlags;
|
|
u8 fileUnitSize;
|
|
u8 interleaveGapSize;
|
|
di16 volumeSequenceNumber;
|
|
u8 fileNameLen;
|
|
char fileName[fileNameLen];
|
|
padding[$ % 2];
|
|
u8 remainingSize = $ - addressof(this);
|
|
if (recordSize > remainingSize) {
|
|
u8 systemUse[recordSize - remainingSize];
|
|
}
|
|
};
|
|
|
|
fn GetSupplementaryEncoding() {
|
|
const u128 escapeSequencesOffset = 89 - 8;
|
|
|
|
str encoding = std::mem::read_string($ + escapeSequencesOffset, 0x20);
|
|
return encoding == "%/@\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
|| encoding == "%/C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
|| encoding == "%/E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
|
};
|
|
|
|
struct VolumeDescriptor {
|
|
VolumeDescriptorTypes type;
|
|
char id[5];
|
|
u8 version;
|
|
|
|
if (type == VolumeDescriptorTypes::PrimaryVolume) {
|
|
padding[1];
|
|
char systemId[0x20];
|
|
char volumeId[0x20];
|
|
padding[8];
|
|
di32 spaceSize;
|
|
padding[0x20];
|
|
di16 setSize;
|
|
di16 sequenceNumber;
|
|
di16 logicalBlockSize;
|
|
di32 pathTableSize;
|
|
PathTablePtr pathTableOffset;
|
|
DirectoryRecord rootDir;
|
|
char setId[0x80];
|
|
char publisherId[0x80];
|
|
char preparerId[0x80];
|
|
char applicationId[0x80];
|
|
char copyrightFileId[0x25];
|
|
char abstractFileId[0x25];
|
|
char bibliographicFileId[0x25];
|
|
StrDateFormat creationTime[[format("FormatStrDate")]];
|
|
StrDateFormat modificationTime[[format("FormatStrDate")]];
|
|
StrDateFormat expirationTime[[format("FormatStrDate")]];
|
|
StrDateFormat effectiveTime[[format("FormatStrDate")]];
|
|
u8 fileStructVersion;
|
|
} else if (type == VolumeDescriptorTypes::SupplementaryVolume && GetSupplementaryEncoding()) {
|
|
u8 flags;
|
|
be char16 systemId[0x10];
|
|
be char16 volumeId[0x10];
|
|
padding[8];
|
|
di32 spaceSize;
|
|
u8 escapeSequences[0x20];
|
|
di16 setSize;
|
|
di16 sequenceNumber;
|
|
di16 logicalBlockSize;
|
|
di32 pathTableSize;
|
|
PathTablePtr pathTableOffset;
|
|
DirectoryRecord rootDir;
|
|
be char16 setId[0x40];
|
|
be char16 publisherId[0x40];
|
|
be char16 preparerId[0x40];
|
|
be char16 applicationId[0x40];
|
|
be char16 copyrightFileId[0x12];
|
|
padding[1];
|
|
be char16 abstractFileId[0x12];
|
|
padding[1];
|
|
be char16 bibliographicFileId[0x12];
|
|
padding[1];
|
|
StrDateFormat creationTime[[format("FormatStrDate")]];
|
|
StrDateFormat modificationTime[[format("FormatStrDate")]];
|
|
StrDateFormat expirationTime[[format("FormatStrDate")]];
|
|
StrDateFormat effectiveTime[[format("FormatStrDate")]];
|
|
u8 fileStructVersion;
|
|
}
|
|
padding[0x800 - $ % 0x800];
|
|
};
|
|
|
|
VolumeDescriptor descriptors[while(std::mem::read_unsigned($, 1) != 0xFF)] @ 0x8000;
|
|
VolumeDescriptor terminator @ $; |