public void LoadFileDataComplete(CASCHandler casc) { if (!casc.FileExists("DBFilesClient\\FileDataComplete.db2")) { return; } Logger.WriteLine("WowRootHandler: loading file names from FileDataComplete.db2..."); using (var s = casc.OpenFile("DBFilesClient\\FileDataComplete.db2")) { WDC1Reader fd = new WDC1Reader(s); Jenkins96 hasher = new Jenkins96(); foreach (var row in fd) { string path = row.Value.GetField <string>(0); string name = row.Value.GetField <string>(1); string fullname = path + name; ulong fileHash = hasher.ComputeHash(fullname); // skip invalid names if (!casc.FileExists(fileHash)) { //Logger.WriteLine("Invalid file name: {0}", fullname); continue; } CASCFile.Files[fileHash] = new CASCFile(fileHash, fullname); } } }
public async Task AnalyzeUnknownFiles(Action <int> progressCallback) { if (_casc == null) { return; } IProgress <int> progress = new Progress <int>(progressCallback); await Task.Run(() => { FileScanner scanner = new FileScanner(_casc, _root); Dictionary <uint, List <string> > idToName = new Dictionary <uint, List <string> >(); if (_casc.Config.GameType == CASCGameType.WoW) { if (_casc.FileExists("DBFilesClient\\SoundEntries.db2")) { using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2")) { DB2Reader se = new DB2Reader(stream); foreach (var row in se) { string name = row.Value.GetField <string>(2); int type = row.Value.GetField <int>(1); bool many = row.Value.GetField <int>(4) > 0; for (int i = 3; i < 23; i++) { uint id = row.Value.GetField <uint>(i); if (!idToName.ContainsKey(id)) { idToName[id] = new List <string>(); } idToName[id].Add("unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg")); } } } } if (_casc.FileExists("DBFilesClient\\SoundKit.db2") && _casc.FileExists("DBFilesClient\\SoundKitEntry.db2") && _casc.FileExists("DBFilesClient\\SoundKitName.db2")) { using (Stream skStream = _casc.OpenFile("DBFilesClient\\SoundKit.db2")) using (Stream skeStream = _casc.OpenFile("DBFilesClient\\SoundKitEntry.db2")) using (Stream sknStream = _casc.OpenFile("DBFilesClient\\SoundKitName.db2")) { WDC1Reader sk = new WDC1Reader(skStream); WDC1Reader ske = new WDC1Reader(skeStream); WDC1Reader skn = new WDC1Reader(sknStream); Dictionary <uint, List <uint> > lookup = new Dictionary <uint, List <uint> >(); foreach (var row in ske) { uint soundKitId = row.Value.GetField <uint>(0); if (!lookup.ContainsKey(soundKitId)) { lookup[soundKitId] = new List <uint>(); } lookup[soundKitId].Add(row.Value.GetField <uint>(1)); } foreach (var row in sk) { string name = skn.GetRow(row.Key).GetField <string>(0).Replace(':', '_'); int type = row.Value.GetField <byte>(6); if (!lookup.TryGetValue(row.Key, out List <uint> ske_entries)) { continue; } bool many = ske_entries.Count > 1; int i = 0; foreach (var fid in ske_entries) { if (!idToName.ContainsKey(fid)) { idToName[fid] = new List <string>(); } idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg")); i++; } } } } } CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder; if (unknownFolder == null) { return; } IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true).ToList(); int numTotal = files.Count(); int numDone = 0; WowRootHandler wowRoot = _casc.Root as WowRootHandler; Jenkins96 Hasher = new Jenkins96(); char[] PathDelimiters = new char[] { '/', '\\' }; foreach (var unknownEntry in files) { CASCFile unknownFile = unknownEntry as CASCFile; if (idToName.TryGetValue((uint)wowRoot.GetFileDataIdByHash(unknownFile.Hash), out List <string> name)) { if (name.Count == 1) { unknownFile.FullName = name[0]; } else { unknownFolder.Entries.Remove(unknownFile.Name); foreach (var file in name) { Logger.WriteLine(file); string[] parts = file.Split(PathDelimiters); string entryName = parts[parts.Length - 1]; ulong filehash = unknownFile.Hash; CASCFile entry = new CASCFile(filehash, file); CASCFile.Files[filehash] = entry; unknownFolder.Entries[entryName] = entry; } } } else { string ext = scanner.GetFileExtension(unknownFile); unknownFile.FullName += ext; if (ext == ".m2") { using (var m2file = _casc.OpenFile(unknownFile.Hash)) using (var br = new BinaryReader(m2file)) { m2file.Position = 0x14; int nameOffs = br.ReadInt32(); m2file.Position = nameOffs + 8; // + sizeof(MD21) string m2name = br.ReadCString(); unknownFile.FullName = "unknown\\" + m2name + ".m2"; } } } progress.Report((int)(++numDone / (float)numTotal * 100)); } _casc.Root.Dump(); }); }
public async Task AnalyzeUnknownFiles(Action <int> progressCallback) { if (_casc == null) { return; } IProgress <int> progress = new Progress <int>(progressCallback); await Task.Run(() => { FileScanner scanner = new FileScanner(_casc, _root); Dictionary <int, List <string> > idToName = new Dictionary <int, List <string> >(); if (_casc.Config.GameType == CASCGameType.WoW && AnalyzeSoundFiles) { if (_casc.FileExists("DBFilesClient\\SoundEntries.db2")) { using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2")) { WDB2Reader se = new WDB2Reader(stream); foreach (var row in se) { string name = row.Value.GetField <string>(2); int type = row.Value.GetField <int>(1); bool many = row.Value.GetField <int>(4) > 0; for (int i = 3; i < 23; i++) { int id = row.Value.GetField <int>(i); if (!idToName.ContainsKey(id)) { idToName[id] = new List <string>(); } idToName[id].Add("unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg")); } } } } if (_casc.FileExists(1237434 /*"DBFilesClient\\SoundKit.db2"*/) && _casc.FileExists(1237435 /*"DBFilesClient\\SoundKitEntry.db2"*/) && _casc.FileExists(1665033 /*"DBFilesClient\\SoundKitName.db2"*/)) { using (Stream skStream = _casc.OpenFile(1237434)) using (Stream skeStream = _casc.OpenFile(1237435)) using (Stream sknStream = _casc.OpenFile(1665033)) { Func <ulong, bool> keyCheckFunc = x => KeyService.GetKey(x) != null; WDC3Reader sk = new WDC3Reader(skStream, keyCheckFunc); WDC3Reader ske = new WDC3Reader(skeStream, keyCheckFunc); WDC3Reader skn = new WDC3Reader(sknStream, keyCheckFunc); Dictionary <int, List <int> > lookup = new Dictionary <int, List <int> >(); foreach (var row in ske) { int soundKitId = row.Value.GetField <int>(0); if (!lookup.ContainsKey(soundKitId)) { lookup[soundKitId] = new List <int>(); } lookup[soundKitId].Add(row.Value.GetField <int>(1)); } foreach (var row in sk) { WDC3Row sknRow = skn.GetRow(row.Key); if (sknRow != null) { string name = sknRow.GetField <string>(0).Replace(':', '_').Replace("\"", ""); int type = row.Value.GetField <byte>(6); if (!lookup.TryGetValue(row.Key, out List <int> ske_entries)) { continue; } bool many = ske_entries.Count > 1; int i = 0; foreach (var fid in ske_entries) { if (!idToName.ContainsKey(fid)) { idToName[fid] = new List <string>(); } if (AddFileDataIdToSoundFiles) { idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg")); } else { idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg")); } i++; } } } } } } CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder; if (unknownFolder == null) { return; } foreach (var kv in idToName) { foreach (var fn in kv.Value) { Logger.WriteLine($"{kv.Key};{fn}"); } } IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true).ToList(); int numTotal = files.Count(); int numDone = 0; WowRootHandler wowRoot = _casc.Root as WowRootHandler; Jenkins96 Hasher = new Jenkins96(); char[] PathDelimiters = new char[] { '/', '\\' }; foreach (var unknownEntry in files) { CASCFile unknownFile = unknownEntry as CASCFile; if (idToName.TryGetValue(wowRoot.GetFileDataIdByHash(unknownFile.Hash), out List <string> name)) { if (name.Count == 1) { unknownFile.FullName = name[0]; } else { unknownFolder.Entries.Remove(unknownFile.Name); foreach (var file in name) { //Logger.WriteLine(file); string[] parts = file.Split(PathDelimiters); string entryName = parts[parts.Length - 1]; ulong filehash = unknownFile.Hash; CASCFile entry = new CASCFile(filehash, file); CASCFile.Files[filehash] = entry; unknownFolder.Entries[entryName] = entry; } } } else { string ext = scanner.GetFileExtension(unknownFile); unknownFile.FullName += ext; if (ext == ".m2") { using (var m2file = _casc.OpenFile(unknownFile.Hash)) using (var br = new BinaryReader(m2file)) { m2file.Position = 0x14; int nameOffs = br.ReadInt32(); m2file.Position = nameOffs + 8; // + sizeof(MD21) string m2name = br.ReadCString(); unknownFile.FullName = "unknown\\" + m2name + ".m2"; Logger.WriteLine($"{wowRoot.GetFileDataIdByHash(unknownFile.Hash)};{unknownFile.FullName}"); //m2file.Position = 0; //while (m2file.Position != m2file.Length) //{ // int chunkType = br.ReadInt32(); // int chunkSize = br.ReadInt32(); // if (chunkType == 0x44494641) // AFID // { // int count = chunkSize / 8; // for (int i = 0; i < count; i++) // { // ushort animId = br.ReadUInt16(); // ushort subAnimId = br.ReadUInt16(); // int FileDataId = br.ReadInt32(); // if (FileDataId != 0) // Logger.WriteLine($"{FileDataId};{wowRoot.GetFileDataIdByHash(unknownFile.Hash)}\\{name}\\{name}{animId:D4}-{subAnimId:D2}.anim"); // } // break; // } // else // { // m2file.Position += chunkSize; // } //} } } } progress.Report((int)(++numDone / (float)numTotal * 100)); } _casc.Root.Dump(); }); }