Example #1
0
        private const uint WDB2FmtSig = 0x32424457; // WDB2

        public WDB2Writer(WDB2Reader reader, IDictionary <int, T> storage, Stream stream) : base(reader)
        {
            WDB2RowSerializer <T> serializer = new WDB2RowSerializer <T>(this);

            serializer.Serialize(storage);

            RecordsCount = storage.Count;

            using (var writer = new BinaryWriter(stream))
            {
                writer.Write(WDB2FmtSig);
                writer.Write(RecordsCount);
                writer.Write(FieldsCount);
                writer.Write(RecordSize);
                writer.Write(StringTableSize);
                writer.Write(reader.TableHash);
                writer.Write(reader.Build);
                writer.Write((uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds());

                if (storage.Count == 0)
                {
                    return;
                }

                // Extended header
                if (reader.Build > 12880)
                {
                    if (reader.MaxIndex == 0)
                    {
                        writer.Write(0);
                        writer.Write(0);
                        writer.Write(reader.LayoutHash);
                        writer.Write(0); // CopyTableSize
                    }
                    else
                    {
                        WriteIndices(writer, serializer, reader.LayoutHash);
                    }
                }

                foreach (var record in serializer.Records)
                {
                    record.Value.CopyTo(writer.BaseStream);
                }

                foreach (var str in StringTable)
                {
                    writer.WriteCString(str.Key);
                }
            }
        }
Example #2
0
        public Storage(Stream stream)
        {
            DB2Reader reader;

            using (stream)
                using (var bin = new BinaryReader(stream))
                {
                    var identifier = new string(bin.ReadChars(4));
                    stream.Position = 0;
                    switch (identifier)
                    {
                    case "WDC3":
                        reader = new WDC3Reader(stream);
                        break;

                    case "WDC2":
                    case "1SLC":
                        reader = new WDC2Reader(stream);
                        break;

                    case "WDC1":
                        reader = new WDC1Reader(stream);
                        break;

                    case "WDB6":
                        reader = new WDB6Reader(stream);
                        break;

                    case "WDB5":
                        reader = new WDB5Reader(stream);
                        break;

                    case "WDB4":
                        reader = new WDB4Reader(stream);
                        break;

                    case "WDB3":
                        reader = new WDB3Reader(stream);
                        break;

                    case "WDB2":
                        reader = new WDB2Reader(stream);
                        break;

                    case "WDBC":
                        reader = new WDBCReader(stream);
                        break;

                    default:
                        throw new Exception("DB type " + identifier + " is not supported!");
                    }
                }

            FieldInfo[] fields = typeof(T).GetFields();

            FieldCache <T>[] fieldCache = new FieldCache <T> [fields.Length];
            for (int i = 0; i < fields.Length; ++i)
            {
                bool indexMapAttribute = reader.Flags.HasFlagExt(DB2Flags.Index) ? Attribute.IsDefined(fields[i], typeof(IndexAttribute)) : false;
                fieldCache[i] = new FieldCache <T>(fields[i], indexMapAttribute);
            }

            Parallel.ForEach(reader.AsEnumerable(), new ParallelOptions()
            {
                MaxDegreeOfParallelism = 1
            }, row =>
            {
                T entry = new T();
                row.Value.GetFields(fieldCache, entry);
                lock (this)
                    Add(row.Value.Id, entry);
            });
        }
Example #3
0
        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("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"))
                                {
                                    WDC3Reader sk  = new WDC3Reader(skStream);
                                    WDC3Reader ske = new WDC3Reader(skeStream);
                                    WDC3Reader skn = new WDC3Reader(sknStream);

                                    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)
                                    {
                                        string name = skn.GetRow(row.Key).GetField <string>(0).Replace(':', '_');
                                        //string name = row.Value.GetField<string>(0).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;
                }

                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";
                                }
                        }
                    }

                    progress.Report((int)(++numDone / (float)numTotal * 100));
                }

                _casc.Root.Dump();
            });
        }