View difference between Paste ID: qFarfjk2 and gw11cGFA
SHOW: | | - or go back to the newest paste.
1
/*
2
 * Filename: RARCTemplate.bt
3
 * Last Modified: 2014-06-12
4
 * Author: Phillip "Antidote" Michael Thomas Stephens
5
 * Purpose: J3D Engine Archives (RARC)
6
 * License: GPLv2
7
 * 010 Version: >= 5.0
8
 */
9
BigEndian();
10
11
struct FileDescriptor
12
{
13-
	ushort ID;
13+
    // All "files" have an ID, it can be used to create a find by ID function
14-
	ushort Unknown1 <format = hex>;
14+
    // rather than searching by name, iirc it corresponds with the file number used in
15-
	ushort Unknown2 <format = hex>;
15+
    // STB files, I think I confirmed this a while back but I'm not entirely sure
16-
	ushort FilenameOffset;
16+
    ushort ID;
17-
	uint   DataStart <format = hex>;
17+
    // The next value appears to be a sort of hash, if it's a directory node and NOT "." or "..", 
18-
	uint   DataSize <format = hex>;
18+
    // it matches it's corresponding node in the node table, not sure of it's purpose, 
19-
	uint   Zero;
19+
    // changing it's value does nothing of merit
20
    ushort Unknown1 <format = hex>;
21
    // Not sure what this one is
22
    ushort Unknown2 <format = hex>;
23
    ushort FilenameOffset;
24-
	char Type[4];
24+
    uint   DataStart <format = hex>;
25-
	uint   FilenameOffset;
25+
    uint   DataSize <format = hex>;
26-
	ushort Unknown <format = hex>;
26+
    uint   Zero;
27-
	ushort FileEntryCount;
27+
28-
	uint   FirstFileStart;
28+
29
struct Node
30
{
31
    // Kind of misleading, it's not really a Type descriptor, 
32
    // it's more of a 4 letter uppercase version of the directories name.
33-
	FileDescriptor Descriptor;
33+
    char   Type[4]; 
34-
	local int tmp = FTell();
34+
    uint   FilenameOffset;
35-
	FSeek((file.StringTableStart + file.HeaderSize) + Descriptor.FilenameOffset);
35+
    // Read the above notation for Unknown1 in FileDescriptor
36-
	string Filename;
36+
    ushort Unknown <format = hex>;
37-
	FSeek(tmp);
37+
    ushort FileEntryCount;
38-
	if (Descriptor.ID == 0xFFFF && Filename != "." && Filename != "..")
38+
    uint   FirstFileStart;
39-
	{
39+
40-
		FSeek(file.FileEntriesStart + (file.Nodes[Descriptor.DataStart].FirstFileStart * sizeof(FileDescriptor)) + 0x20);
40+
41-
		FileEntry FileEntries[file.Nodes[Descriptor.DataStart].FileEntryCount] <optimize = false>;
41+
42-
		FSeek(tmp);
42+
43-
	}
43+
44-
	else if (Filename != "." && Filename != "..")
44+
    FileDescriptor Descriptor;
45-
	{
45+
    local int tmp = FTell();
46-
		FSeek(file.DataStart + Descriptor.DataStart + 0x20);
46+
    FSeek((file.StringTableStart + file.HeaderSize) + Descriptor.FilenameOffset);
47-
		ubyte Data[Descriptor.DataSize];
47+
    string Filename;
48-
		FSeek(tmp);
48+
    FSeek(tmp);
49-
	}
49+
    // If the descriptor's ID is 0xFFFF it's a directory, otherwise it's a file
50
    if (Descriptor.ID == 0xFFFF && Filename != "." && Filename != "..")
51
    {
52
        // If we're a directory AND we're not "." or ".." we read in our children
53
        FSeek(file.FileEntriesStart + (file.Nodes[Descriptor.DataStart].FirstFileStart * sizeof(FileDescriptor)) + 0x20);
54-
	uint Magic <format = hex>;
54+
        FileEntry FileEntries[file.Nodes[Descriptor.DataStart].FileEntryCount] <optimize = false>;
55-
	if (Magic != 0x52415243)
55+
        FSeek(tmp);
56-
	{
56+
        // The reason we don't want to handle "." and ".." is because of a known quirk in computers, 
57-
		Warning("Not a valid RARC File");
57+
        // I won't elaborate but here is a link on the issue:
58-
		return;
58+
        // http://stackoverflow.com/questions/2630054/does-c-limit-recursion-depth
59-
	}
59+
        // I.E, blame the stack implementation :P
60-
	uint FileSize <format = hex>;
60+
    }
61-
	if (FileSize != FileSize())
61+
    else if (Filename != "." && Filename != "..")
62-
	{
62+
    {
63-
		Warning("Malformed file, stored size does not match actual size");
63+
        FSeek(file.DataStart + Descriptor.DataStart + 0x20);
64-
		return;
64+
        ubyte Data[Descriptor.DataSize];
65-
	}
65+
        FSeek(tmp);
66-
	uint HeaderSize;
66+
    }
67-
	uint DataStart <format = hex>;
67+
68-
	uint Unknown[4] <format = hex>;
68+
69-
	uint NodeCount;
69+
70-
	uint Unknown2[2] <format = hex>;
70+
71-
	uint FileEntriesStart <format = hex>;
71+
    // The archive's Magic, must always be "RARC", if it's "Yaz0" it's "compressed"
72-
	uint StringTableSize <format = hex>;
72+
    uint Magic <format = hex>;
73-
	uint StringTableStart <format = hex>;
73+
    if (Magic != 0x52415243)
74-
	uint Unknown4[2] <format = hex>;
74+
    {
75
        Warning("Not a valid RARC File");
76-
	Node Nodes[NodeCount] <optimize = false>;
76+
        return;
77-
	local int tmp = FTell();
77+
    }
78-
	FSeek(FileEntriesStart + Nodes[0].FirstFileStart + 0x20);
78+
    // This value MUST equal the total size of the file, if it doesn't the game will reject it
79-
	FileEntry FileEntries[Nodes[0].FileEntryCount] <optimize = false>;
79+
    // if it's a vital archive the game will hang, otherwise the data simply won't be loaded
80-
	FSeek(tmp);
80+
    uint FileSize <format = hex>;
81
    if (FileSize != FileSize())
82
    {
83
        Warning("Malformed file, stored size does not match actual size");
84
        return;
85
    }
86
    uint HeaderSize;
87
    uint DataStart <format = hex>;
88
    // Appears to be a series of offsets, they do nothing of merit
89
    uint Unknown[4] <format = hex>;
90
    uint NodeCount;
91
    // These appear to be counts of some sort, again they do nothing of merit.
92
    uint Unknown2[2] <format = hex>;
93
    uint FileEntriesStart <format = hex>;
94
    uint StringTableSize <format = hex>;
95
    uint StringTableStart <format = hex>;
96
    uint Unknown4[2] <format = hex>;
97
    
98
    Node Nodes[NodeCount] <optimize = false>;
99
    local int tmp = FTell();
100
    FSeek(FileEntriesStart + Nodes[0].FirstFileStart + 0x20);
101
    FileEntry FileEntries[Nodes[0].FileEntryCount] <optimize = false>;
102
    FSeek(tmp);
103
}file;