forked from WerWolv/ImHex-Patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sit5.hexpat
115 lines (93 loc) · 3.28 KB
/
sit5.hexpat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md
#pragma endian big
#pragma MIME application/x-stuffit
#include <std/io.pat>
#include <std/time.pat>
namespace v5 {
bitfield Flags1 {
padding : 1;
folder : 1;
encrypted : 1;
padding : 5;
} [[left_to_right]];
bitfield Flags2 {
padding : 7;
resource_fork : 1;
padding : 8;
} [[left_to_right]];
using MacOSHFSPlusDate = u32 [[format("v5::format_macos_date")]];
fn format_macos_date(MacOSHFSPlusDate date) {
return std::time::format(std::time::to_utc(date - 2082844800));
};
struct Header {
char magic[0x50];
u32 unknown1;
u32 archiveSize;
u32 entriesOffset;
u32 unknown2;
};
struct EntryHeader {
u32 magic;
u8 version;
u8 unknown1;
u16 headerSize;
u8 unknown2;
Flags1 flags;
MacOSHFSPlusDate creationDate, modificationDate;
u32 prevEntryOffset, nextEntryOffset, parentEntryOffset;
u16 nameSize;
u16 headerChecksum;
u32 dataForkUncompressedLength, dataForkCompressedLength;
u16 dataForkChecksum;
u16 unknown3;
};
enum CompressionMethod : u8 {
None = 0x00, // No compression
Rle90 = 0x01, // Run length encoding
Compress = 0x02, // Compress LZW algorithm, 14 bit max code length, block mode
StuffIt3 = 0x03, // Simple Huffman encoding for individual bytes
StuffIt5 = 0x05, // LZAH
StuffIt8 = 0x08, // Miller-Wegman
StuffIt13 = 0x0D, // LZSS and Huffman
Stuffit14 = 0x0E, // Unknown
StuffItArsenic = 0x0F // BWT and arithmetic coding
};
struct Entry {
EntryHeader header;
if (header.flags.folder) {
u16 numFiles;
if (header.dataForkUncompressedLength)
std::print("Folder entry {} is special!", std::core::array_index());
} else {
CompressionMethod compressionMethod;
}
u8 passwordDataLength;
u8 passwordInformation[passwordDataLength];
char fileName[header.nameSize];
u16 commentSize;
u16 unknown2;
char comment[commentSize];
if (!header.flags.folder) {
Flags2 flags;
u16 unknown3;
char fileType[4];
u32 fileCreator;
u16 macOSFinderFlags;
u32 unknown4;
u32 unknown5;
u8 unknown6[6];
if (header.version == 1)
u32 unknown7;
u8 compressedData[header.dataForkCompressedLength] [[sealed]];
if (header.nextEntryOffset == 0x00)
break;
else
$ = header.nextEntryOffset;
}
};
struct StuffIt {
Header header;
Entry entries[while(true)] @ header.entriesOffset;
};
}
v5::StuffIt stuffIt @ 0x00;