-
Notifications
You must be signed in to change notification settings - Fork 3
/
CPakFile.bt
134 lines (123 loc) · 3.42 KB
/
CPakFile.bt
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef _CPAKFILE
#define _CPAKFILE
struct File;
struct CPakFile;
typedef struct
{
FourCC type;
GUID id;
if (!isDKCTF)
{
uint32 versionA;
uint32 versionB;
}
uint64 offset <format=hex>;
if (!isDKCTF)
{
uint64 decompressedSize <format=hex>;
}
uint64 size <format=hex>;
if (isDKCTF)
{
local uint64 decompressedSize <hidden=true> = size;
}
local uint64 pos <format=hex, hidden=true> = FTell();
FSeek(offset);
if (size == decompressedSize) {
File data <size=size>;
} else {
CompressionType compressionType;
byte pad[3] <hidden=true>;
byte compressedData[size - 4];
}
FSeek(pos);
} AssetDirectoryEntry <
size=(isDKCTF ? 36 : 52), // Parse on-demand
name=AssetDirectoryEntryName,
comment=(SizeComment(this.size))
>;
string AssetDirectoryEntryName(AssetDirectoryEntry& entry)
{
if (isDKCTF) {
// Read the chunk ver and subver from form descriptor
return Str("%s v%d.%d %s", entry.type, entry.data.form.readerVersion, entry.data.form.writerVersion, GUIDToString(entry.id)); //Fix broken DKCTF version display
} else {
return Str("%s v%d.%d %s", entry.type, entry.versionA, entry.versionB, GUIDToString(entry.id));
}
}
typedef struct
{
GUID id;
uint32 offset <format=hex>;
// Find the FourCC for the asset ID
// Assumes TOCC chunk 0 is ADIR
local FourCC type <hidden=true>;
local uint64 fileOffset <hidden=true>;
local uint32 i <hidden=true>;
for (i = 0; i < pak.chunk[0].count; i++) {
if (pak.chunk[0].entry[i].id == id) {
type = pak.chunk[0].entry[i].type;
fileOffset = pak.chunk[0].entry[i].offset;
break;
}
}
local uint64 pos <format=hex, hidden=true> = FTell();
FSeek(start + offset);
uint32 size <format=hex>;
Meta data(type, size, fileOffset);
FSeek(pos);
} MetaEntry <
size=20, // Parse on-demand
name=(Str("%s %s", this.type, GUIDToString(this.id))),
comment=(SizeComment(size))
>;
typedef struct
{
// Byteswapped
uint32 type <read=FourCCInt>;
GUID id;
// Wii U DKCTF uses a null terminated string here
// but PACK/TOCC version is the same
if (!isDKCTF || ReadByte() == 0) {
uint32 length;
char name[length];
} else {
string name;
}
} StringEntry <
name=(Str("%s (%s) %s", name, FourCCInt(type), GUIDToString(id)))
>;
typedef struct(CPakFile& pak)
{
ChunkDescriptor chunk;
local uint64 start <format=hex, hidden=true> = FTell();
switch (chunk.id)
{
case "ADIR":
uint32 count <format=decimal, name="ADIR entry count">;
AssetDirectoryEntry entry[count] <optimize=false>;
break;
case "META":
uint32 count <format=decimal, name="META entry count">;
MetaEntry entry[count] <optimize=false>;
break;
case "STRG":
uint32 count <format=decimal, name="STRG entry count">;
StringEntry entry[count] <optimize=false>;
break;
}
FSeek(start + chunk.size);
} TOCChunk <
name=(Str("%s chunk", chunk.id)),
comment=(Str("%d entries", count))
>;
typedef struct
{
FormDescriptor toc;
local uint64 start <format=hex, hidden=true> = FTell();
while (FTell() < start + toc.size)
{
TOCChunk chunk(this);
}
} CPakFile <name="PACK chunks">;
#endif// _CPAKFILE