Skip to content

Commit 506cd99

Browse files
8.2 root change handling
1 parent ee6bcad commit 506cd99

File tree

1 file changed

+64
-14
lines changed

1 file changed

+64
-14
lines changed

CASCEdit/Handlers/RootHandler.cs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@ public class RootHandler : IDisposable
2323
private uint maxId = 0;
2424
private readonly uint minimumId;
2525
private readonly EncodingMap encodingMap;
26-
27-
public RootHandler()
26+
private int namedFiles = 0;
27+
private int allFiles = 0;
28+
private int parsedFiles = 0;
29+
private const int headerMagic = 0x4D465354; // MFST
30+
private const string customFileDataDirectory = "filedatas"; // we generate a custom namehash for files without one ( 8.2 root change ), therefore we need allow some options.
31+
private const string customFileDataPrefix = "filedata_";
32+
33+
public RootHandler()
2834
{
2935
GlobalRoot = new RootChunk() { ContentFlags = ContentFlags.None, LocaleFlags = LocaleFlags.All_WoW };
3036
encodingMap = new EncodingMap(EncodingType.ZLib, 9);
@@ -37,7 +43,20 @@ public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0)
3743

3844
BinaryReader stream = new BinaryReader(data);
3945

40-
long length = stream.BaseStream.Length;
46+
// 8.2 root change
47+
int magic = stream.ReadInt32();
48+
bool newFormat = magic == headerMagic;
49+
if (newFormat)
50+
{
51+
allFiles = stream.ReadInt32();
52+
namedFiles = stream.ReadInt32();
53+
}
54+
else
55+
{
56+
stream.BaseStream.Position = 0;
57+
}
58+
59+
long length = stream.BaseStream.Length;
4160
while (stream.BaseStream.Position < length)
4261
{
4362
RootChunk chunk = new RootChunk()
@@ -47,8 +66,10 @@ public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0)
4766
LocaleFlags = (LocaleFlags)stream.ReadUInt32(),
4867
};
4968

50-
// set the global root
51-
if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None)
69+
parsedFiles += (int)chunk.Count;
70+
71+
// set the global root
72+
if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None)
5273
GlobalRoot = chunk;
5374

5475
uint fileDataIndex = 0;
@@ -66,14 +87,41 @@ public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0)
6687
chunk.Entries.Add(entry);
6788
}
6889

69-
foreach (var entry in chunk.Entries)
70-
{
71-
entry.CEKey = new MD5Hash(stream);
72-
entry.NameHash = stream.ReadUInt64();
73-
maxId = Math.Max(maxId, entry.FileDataId);
74-
}
75-
76-
Chunks.Add(chunk);
90+
if (newFormat)
91+
{
92+
foreach (var entry in chunk.Entries)
93+
{
94+
entry.CEKey = new MD5Hash(stream);
95+
maxId = Math.Max(maxId, entry.FileDataId);
96+
}
97+
98+
if (parsedFiles > allFiles - namedFiles)
99+
{
100+
foreach (var entry in chunk.Entries)
101+
{
102+
entry.NameHash = stream.ReadUInt64();
103+
}
104+
}
105+
else // no namehash, so we generate a custom one
106+
{
107+
foreach (var entry in chunk.Entries)
108+
{
109+
entry.NameHash = new Jenkins96().ComputeHash($"{customFileDataDirectory}/{customFileDataPrefix}" + entry.FileDataId);
110+
}
111+
}
112+
113+
}
114+
else
115+
{
116+
foreach (var entry in chunk.Entries)
117+
{
118+
entry.CEKey = new MD5Hash(stream);
119+
entry.NameHash = stream.ReadUInt64();
120+
maxId = Math.Max(maxId, entry.FileDataId);
121+
}
122+
}
123+
124+
Chunks.Add(chunk);
77125
}
78126

79127
if (GlobalRoot == null)
@@ -139,7 +187,9 @@ public void AddEntry(string path, CASResult file)
139187

140188
GlobalRoot.Entries.Add(entry); // Insert into the Global Root
141189
maxId = Math.Max(entry.FileDataId, maxId); // Update the max id
142-
}
190+
191+
cache?.AddOrUpdate(new CacheEntry(entry, file.EKey)); // If not done, sometimes files will not be added.
192+
}
143193
else
144194
{ // Existing file, we just have to update the data hash
145195
foreach (var entry in entries)

0 commit comments

Comments
 (0)