Example #1
0
        public override void ReadHeader(ref BinaryReader dbReader, string signature)
        {
            ReadBaseHeader(ref dbReader, signature);

            TableHash      = dbReader.ReadUInt32();
            LayoutHash     = dbReader.ReadInt32();
            MinId          = dbReader.ReadInt32();
            MaxId          = dbReader.ReadInt32();
            Locale         = dbReader.ReadInt32();
            CopyTableSize  = dbReader.ReadInt32();
            Flags          = (HeaderFlags)dbReader.ReadUInt16();
            IdIndex        = dbReader.ReadUInt16();
            TotalFieldSize = dbReader.ReadUInt32();

            PackedDataOffset     = dbReader.ReadInt32();
            RelationshipCount    = dbReader.ReadUInt32();
            OffsetTableOffset    = dbReader.ReadInt32();
            IndexSize            = dbReader.ReadInt32();
            ColumnMetadataSize   = dbReader.ReadInt32();
            SparseDataSize       = dbReader.ReadInt32();
            PalletDataSize       = dbReader.ReadInt32();
            RelationshipDataSize = dbReader.ReadInt32();

            //Gather field structures
            FieldStructure = new List <FieldStructureEntry>();
            for (int i = 0; i < FieldCount; i++)
            {
                var field = new FieldStructureEntry(dbReader.ReadInt16(), dbReader.ReadUInt16());
                FieldStructure.Add(field);
            }

            recordData = dbReader.ReadBytes((int)(RecordCount * RecordSize));
            Array.Resize(ref recordData, recordData.Length + 8);
        }
Example #2
0
        /// <summary>
        /// Generates a Bit map for all columns as the Blizzard one combines array columns
        /// </summary>
        /// <returns></returns>
        public FieldStructureEntry[] GetBits()
        {
            FieldStructureEntry[] bits = new FieldStructureEntry[Data.Columns.Count];
            if (!Header.IsTypeOf <WDB5>())
            {
                return(bits);
            }

            var fields = ((WDB5)Header).FieldStructure;
            int c      = 0;

            for (int i = 0; i < TableStructure.Fields.Count; i++)
            {
                Field f = TableStructure.Fields[i];
                for (int x = 0; x < f.ArraySize; x++)
                {
                    bits[c]                = new FieldStructureEntry(0, 0);
                    bits[c].Bits           = fields[i]?.Bits ?? 0;
                    bits[c].CommonDataType = fields[i]?.CommonDataType ?? 0xFF;
                    c++;
                }
            }

            return(bits);
        }
Example #3
0
        /// <summary>
        /// Generates a Bit map for all columns as the Blizzard one combines array columns
        /// </summary>
        /// <returns></returns>
        public FieldStructureEntry[] GetBits()
        {
            FieldStructureEntry[] bits = new FieldStructureEntry[TableStructure.Length];
            if (!Header.IsTypeOf <WDB5>())
            {
                return(bits);
            }

            int c = 0, f = 0;

            for (int i = 0; i < TableStructure.Length; i++)
            {
                var dbField = TableStructure[i].GetCustomAttribute <DBFieldAttribute>();
                if (dbField != null && dbField.Bits > -1)
                {
                    bits[c] = new FieldStructureEntry(dbField.Bits, 0, (byte)Convert.ChangeType((dbField.DefaultValue ?? 0xFF), TypeCode.Byte));
                }
                else
                {
                    FieldStructureEntry field = Header.FieldStructure[f];
                    bits[c] = new FieldStructureEntry(field?.Bits ?? 0, 0, field?.CommonDataType ?? 0xFF);
                    f++;
                }

                c++;
            }

            return(bits);
        }
 public static void WriteUInt64(this BinaryWriter bw, ulong value, FieldStructureEntry map = null)
 {
     if (map == null)
     {
         bw.Write(value);
     }
     else
     {
         bw.Write(BitConverter.GetBytes(value), 0, map.ByteCount);
     }
 }
        public static ulong ReadUInt64(this BinaryReader br, FieldStructureEntry map = null)
        {
            if (map == null)
            {
                return(br.ReadUInt64());
            }

            byte[] b = new byte[sizeof(ulong)];
            for (int i = 0; i < map.ByteCount; i++)
            {
                b[i] = br.ReadByte();
            }

            return(BitConverter.ToUInt64(b, 0));
        }
Example #6
0
        public override void ReadHeader(ref BinaryReader dbReader, string signature)
        {
            ReadBaseHeader(ref dbReader, signature);

            TableHash           = dbReader.ReadUInt32();
            LayoutHash          = dbReader.ReadInt32();
            MinId               = dbReader.ReadInt32();
            MaxId               = dbReader.ReadInt32();
            Locale              = dbReader.ReadInt32();
            CopyTableSize       = dbReader.ReadInt32();
            Flags               = (HeaderFlags)dbReader.ReadUInt16();
            IdIndex             = dbReader.ReadUInt16();
            TotalFieldSize      = dbReader.ReadUInt32();
            CommonDataTableSize = dbReader.ReadUInt32();

            if (HasIndexTable)
            {
                IdIndex = 0;                 //Ignored if Index Table
            }
            InternalRecordSize = RecordSize; //RecordSize header field is not right anymore

            //Gather field structures
            FieldStructure = new List <FieldStructureEntry>();
            for (var i = 0; i < FieldCount; i++)
            {
                FieldStructureEntry field = new FieldStructureEntry(dbReader.ReadInt16(),
                                                                    (ushort)(dbReader.ReadUInt16() + (HasIndexTable ? 4 : 0)));
                FieldStructure.Add(field);

                if (i > 0)
                {
                    FieldStructure[i - 1].SetLength(field);
                }
            }

            if (HasIndexTable)
            {
                InternalRecordSize += 4;
                FieldCount++;
                FieldStructure.Insert(0, new FieldStructureEntry(0, 0));

                if (FieldCount > 1)
                {
                    FieldStructure[1].SetLength(FieldStructure[0]);
                }
            }
        }
Example #7
0
        public override void ReadHeader(ref BinaryReader dbReader, string signature)
        {
            base.ReadHeader(ref dbReader, signature);

            TableHash     = dbReader.ReadUInt32();
            LayoutHash    = dbReader.ReadInt32();
            MinId         = dbReader.ReadInt32();
            MaxId         = dbReader.ReadInt32();
            Locale        = dbReader.ReadInt32();
            CopyTableSize = dbReader.ReadInt32();
            Flags         = (HeaderFlags)dbReader.ReadUInt16();
            IdIndex       = dbReader.ReadUInt16();

            if (Flags.HasFlag(HeaderFlags.IndexMap))
            {
                IdIndex = 0; //Ignored if Index Table
            }
            //Gather field structures
            FieldStructure = new List <FieldStructureEntry>();
            for (var i = 0; i < FieldCount; i++)
            {
                FieldStructureEntry field = new FieldStructureEntry(dbReader.ReadInt16(),
                                                                    (ushort)(dbReader.ReadUInt16() + (HasIndexTable ? 4 : 0)));
                FieldStructure.Add(field);

                if (i > 0)
                {
                    FieldStructure[i - 1].SetLength(field);
                }
            }

            if (HasIndexTable)
            {
                FieldCount++;
                FieldStructure.Insert(0, new FieldStructureEntry(0, 0));

                if (FieldCount > 1)
                {
                    FieldStructure[1].SetLength(FieldStructure[0]);
                }
            }
        }
Example #8
0
        static void ReadHeader(BinaryReader reader)
        {
            Header                 = new DB6Header();
            Header.Signature       = reader.ReadUInt32();
            Header.RecordCount     = reader.ReadUInt32();
            Header.FieldCount      = reader.ReadUInt32();
            Header.RecordSize      = reader.ReadUInt32();
            Header.StringTableSize = reader.ReadUInt32(); // also offset for sparse table

            Header.TableHash       = reader.ReadUInt32();
            Header.LayoutHash      = reader.ReadUInt32();
            Header.MinId           = reader.ReadInt32();
            Header.MaxId           = reader.ReadInt32();
            Header.Locale          = reader.ReadInt32();
            Header.CopyTableSize   = reader.ReadInt32();
            Header.Flags           = (HeaderFlags)reader.ReadUInt16();
            Header.IdIndex         = reader.ReadUInt16();
            Header.TotalFieldCount = reader.ReadUInt32();

            Header.BitpackedDataOffset  = reader.ReadUInt32();
            Header.LookupColumnCount    = reader.ReadUInt32();
            Header.OffsetTableOffset    = reader.ReadUInt32();
            Header.IdListSize           = reader.ReadUInt32();
            Header.ColumnMetaSize       = reader.ReadUInt32();
            Header.CommonDataSize       = reader.ReadUInt32();
            Header.PalletDataSize       = reader.ReadUInt32();
            Header.RelationshipDataSize = reader.ReadUInt32();

            //Gather field structures
            FieldStructure = new List <FieldStructureEntry>();
            for (int i = 0; i < Header.FieldCount; i++)
            {
                var field = new FieldStructureEntry(reader.ReadInt16(), reader.ReadUInt16());
                FieldStructure.Add(field);
            }
        }
Example #9
0
 public void SetLength(FieldStructureEntry nextField)
 {
     this.Length = Math.Max(1, (int)Math.Floor((nextField.Offset - this.Offset) / (double)this.ByteCount));
 }
Example #10
0
        public new Dictionary <int, byte[]> ReadOffsetData(BinaryReader dbReader, long pos)
        {
            var CopyTable  = new Dictionary <int, byte[]>();
            var offsetmap  = new List <Tuple <int, short> >();
            var firstindex = new Dictionary <int, OffsetDuplicate>();

            long commonDataTablePos = dbReader.BaseStream.Length - CommonDataTableSize;
            long copyTablePos       = commonDataTablePos - CopyTableSize;
            long indexTablePos      = copyTablePos - (HasIndexTable ? RecordCount * 4 : 0);

            int[] m_indexes = null;

            //Offset Map
            if (HasOffsetTable)
            {
                // Records table
                dbReader.Scrub(StringBlockSize);

                for (var i = 0; i < MaxId - MinId + 1; i++)
                {
                    int   offset = dbReader.ReadInt32();
                    short length = dbReader.ReadInt16();

                    if (offset == 0 || length == 0)
                    {
                        continue;
                    }

                    //Special case, may contain duplicates in the offset map that we don't want
                    if (CopyTableSize == 0)
                    {
                        if (!firstindex.ContainsKey(offset))
                        {
                            firstindex.Add(offset, new OffsetDuplicate(offsetmap.Count, firstindex.Count));
                        }
                        else
                        {
                            OffsetDuplicates.Add(MinId + i, firstindex[offset].VisibleIndex);
                        }
                    }

                    offsetmap.Add(new Tuple <int, short>(offset, length));
                }
            }

            if (HasRelationshipData)
            {
                dbReader.BaseStream.Position += (MaxId - MinId + 1) * 4;
            }

            //Index table
            if (HasIndexTable)
            {
                //Offset map alone reads straight into this others may not
                if (!HasOffsetTable || HasRelationshipData)
                {
                    dbReader.Scrub(indexTablePos);
                }

                m_indexes = new int[RecordCount];
                for (var i = 0; i < RecordCount; i++)
                {
                    m_indexes[i] = dbReader.ReadInt32();
                }
            }

            //Extract record data
            for (var i = 0; i < Math.Max(RecordCount, offsetmap.Count); i++)
            {
                if (HasOffsetTable && m_indexes != null)
                {
                    int id  = m_indexes[Math.Min(CopyTable.Count, m_indexes.Length - 1)];
                    var map = offsetmap[i];

                    if (CopyTableSize == 0 && firstindex[map.Item1].HiddenIndex != i) //Ignore duplicates
                    {
                        continue;
                    }

                    dbReader.Scrub(map.Item1);

                    var recordbytes = BitConverter.GetBytes(id).Concat(dbReader.ReadBytes(map.Item2));

                    CopyTable.Add(id, recordbytes.ToArray());
                }
                else
                {
                    dbReader.Scrub(pos + i * RecordSize);
                    byte[] recordbytes = dbReader.ReadBytes((int)RecordSize).ToArray();

                    if (HasIndexTable)
                    {
                        var newrecordbytes = BitConverter.GetBytes(m_indexes[i]).Concat(recordbytes);
                        CopyTable.Add(m_indexes[i], newrecordbytes.ToArray());
                    }
                    else
                    {
                        int bytecount = FieldStructure[IdIndex].ByteCount;
                        int offset    = FieldStructure[IdIndex].Offset;

                        var id = 0;
                        for (var j = 0; j < bytecount; j++)
                        {
                            id |= recordbytes[offset + j] << (j * 8);
                        }

                        CopyTable.Add(id, recordbytes);
                    }
                }
            }

            //CopyTable
            if (CopyTableSize != 0 && copyTablePos != dbReader.BaseStream.Length)
            {
                dbReader.Scrub(copyTablePos);
                while (dbReader.BaseStream.Position != dbReader.BaseStream.Length)
                {
                    int id     = dbReader.ReadInt32();
                    int idcopy = dbReader.ReadInt32();

                    byte[] copyRow = CopyTable[idcopy];
                    var    newRow  = new byte[copyRow.Length];
                    Array.Copy(copyRow, newRow, newRow.Length);
                    Array.Copy(BitConverter.GetBytes(id), newRow, sizeof(int));

                    CopyTable.Add(id, newRow);
                }
            }

            //CommonDataTable
            if (CommonDataTableSize > 0)
            {
                dbReader.Scrub(commonDataTablePos);
                int columncount = dbReader.ReadInt32();

                var commondatalookup = new Dictionary <int, byte[]> [columncount];

                //Initial Data extraction
                for (var i = 0; i < columncount; i++)
                {
                    int   count = dbReader.ReadInt32();
                    byte  type  = dbReader.ReadByte();
                    short bit   = CommonDataBits[type];
                    int   size  = (32 - bit) >> 3;

                    commondatalookup[i] = new Dictionary <int, byte[]>();

                    //New field not defined in header
                    if (i > FieldStructure.Count - 1)
                    {
                        var offset = (ushort)(FieldStructure.Count == 0
                            ? 0
                            : FieldStructure[i - 1].Offset + FieldStructure[i - 1].ByteCount);
                        FieldStructure.Add(new FieldStructureEntry(bit, offset, type));

                        if (FieldStructure.Count > 1)
                        {
                            FieldStructure[i - 1].SetLength(FieldStructure[i]);
                        }
                    }

                    for (var x = 0; x < count; x++)
                    {
                        commondatalookup[i].Add(dbReader.ReadInt32(), dbReader.ReadBytes(size));

                        if (TableStructure == null || TableStructure?.Build >= 24492)
                        {
                            dbReader.ReadBytes(4 - size);
                        }
                    }
                }

                int[] ids = CopyTable.Keys.ToArray();
                foreach (int id in ids)
                {
                    for (var i = 0; i < commondatalookup.Length; i++)
                    {
                        if (!FieldStructure[i].CommonDataColumn)
                        {
                            continue;
                        }

                        var    col          = commondatalookup[i];
                        string defaultValue = TableStructure?.Fields?[i]?.DefaultValue;
                        defaultValue = string.IsNullOrEmpty(defaultValue) ? "0" : defaultValue;

                        FieldStructureEntry field = FieldStructure[i];
                        var zeroData = new byte[field.ByteCount];
                        if (defaultValue != "0")
                        {
                            switch (field.CommonDataType)
                            {
                            case 1:
                                zeroData = BitConverter.GetBytes(ushort.Parse(defaultValue));
                                break;

                            case 2:
                                zeroData = new[] { byte.Parse(defaultValue) };
                                break;

                            case 3:
                                zeroData = BitConverter.GetBytes(float.Parse(defaultValue));
                                break;

                            case 4:
                                zeroData = BitConverter.GetBytes(int.Parse(defaultValue));
                                break;
                            }
                        }

                        byte[] currentData = CopyTable[id];
                        byte[] data        = col.ContainsKey(id) ? col[id] : zeroData;
                        Array.Resize(ref currentData, currentData.Length + data.Length);
                        Array.Copy(data, 0, currentData, field.Offset, data.Length);
                        CopyTable[id] = currentData;
                    }
                }

                commondatalookup   = null;
                InternalRecordSize = (uint)CopyTable.Values.First().Length;
            }

            return(CopyTable);
        }
Example #11
0
        public override void ReadHeader(ref BinaryReader dbReader, string signature)
        {
            ReadBaseHeader(ref dbReader, signature);

            TableHash        = dbReader.ReadUInt32();
            LayoutHash       = dbReader.ReadInt32();
            MinId            = dbReader.ReadInt32();
            MaxId            = dbReader.ReadInt32();
            Locale           = dbReader.ReadInt32();
            Flags            = (HeaderFlags)dbReader.ReadUInt16();
            IdIndex          = dbReader.ReadUInt16();
            TotalFieldSize   = dbReader.ReadUInt32();
            PackedDataOffset = dbReader.ReadInt32();

            RelationshipCount  = dbReader.ReadUInt32();
            ColumnMetadataSize = dbReader.ReadInt32();
            SparseDataSize     = dbReader.ReadInt32();
            PalletDataSize     = dbReader.ReadInt32();

            SectionCount = dbReader.ReadInt32();

            // TODO convert to array when the time comes
            Unknown1             = dbReader.ReadInt32();
            Unknown2             = dbReader.ReadInt32();
            RecordDataOffset     = dbReader.ReadInt32();
            RecordDataRowCount   = dbReader.ReadInt32();
            RecordDataStringSize = dbReader.ReadInt32();
            CopyTableSize        = dbReader.ReadInt32();
            OffsetTableOffset    = dbReader.ReadInt32();
            IndexSize            = dbReader.ReadInt32();
            RelationshipDataSize = dbReader.ReadInt32();

            if (RecordCount == 0 || FieldCount == 0)
            {
                return;
            }

            //Gather field structures
            FieldStructure = new List <FieldStructureEntry>();
            for (int i = 0; i < FieldCount; i++)
            {
                var field = new FieldStructureEntry(dbReader.ReadInt16(), dbReader.ReadUInt16());
                FieldStructure.Add(field);
            }

            // ColumnMeta
            ColumnMeta = new List <ColumnStructureEntry>();
            for (int i = 0; i < FieldCount; i++)
            {
                var column = new ColumnStructureEntry()
                {
                    RecordOffset       = dbReader.ReadUInt16(),
                    Size               = dbReader.ReadUInt16(),
                    AdditionalDataSize = dbReader.ReadUInt32(),                     // size of pallet / sparse values
                    CompressionType    = (CompressionType)dbReader.ReadUInt32(),
                    BitOffset          = dbReader.ReadInt32(),
                    BitWidth           = dbReader.ReadInt32(),
                    Cardinality        = dbReader.ReadInt32()
                };

                // preload arraysizes
                if (column.CompressionType == CompressionType.None)
                {
                    column.ArraySize = Math.Max(column.Size / FieldStructure[i].BitCount, 1);
                }
                else if (column.CompressionType == CompressionType.PalletArray)
                {
                    column.ArraySize = Math.Max(column.Cardinality, 1);
                }

                ColumnMeta.Add(column);
            }

            // Pallet values
            for (int i = 0; i < ColumnMeta.Count; i++)
            {
                if (ColumnMeta[i].CompressionType == CompressionType.Pallet || ColumnMeta[i].CompressionType == CompressionType.PalletArray)
                {
                    int elements    = (int)ColumnMeta[i].AdditionalDataSize / 4;
                    int cardinality = Math.Max(ColumnMeta[i].Cardinality, 1);

                    ColumnMeta[i].PalletValues = new List <byte[]>();
                    for (int j = 0; j < elements / cardinality; j++)
                    {
                        ColumnMeta[i].PalletValues.Add(dbReader.ReadBytes(cardinality * 4));
                    }
                }
            }

            // Sparse values
            for (int i = 0; i < ColumnMeta.Count; i++)
            {
                if (ColumnMeta[i].CompressionType == CompressionType.Sparse)
                {
                    ColumnMeta[i].SparseValues = new Dictionary <int, byte[]>();
                    for (int j = 0; j < ColumnMeta[i].AdditionalDataSize / 8; j++)
                    {
                        ColumnMeta[i].SparseValues[dbReader.ReadInt32()] = dbReader.ReadBytes(4);
                    }
                }
            }

            // RecordData
            recordData = dbReader.ReadBytes((int)(RecordCount * RecordSize));
            Array.Resize(ref recordData, recordData.Length + 8);

            Flags &= ~HeaderFlags.SecondIndex;             // appears to be obsolete now
        }
Example #12
0
        private static void WriteValue <T>(BinaryWriter bw, DBEntry <T> entry, object value, uint padding, StringTable st, FieldStructureEntry bits, bool duplicates) where T : class
        {
            switch (Type.GetTypeCode(value.GetType()))
            {
            case TypeCode.SByte:
                bw.Write((sbyte)value);
                bw.BaseStream.Position += sizeof(sbyte) * padding;
                break;

            case TypeCode.Byte:
                bw.Write((byte)value);
                bw.BaseStream.Position += sizeof(byte) * padding;
                break;

            case TypeCode.Int16:
                bw.Write((short)value);
                bw.BaseStream.Position += sizeof(short) * padding;
                break;

            case TypeCode.UInt16:
                bw.Write((ushort)value);
                bw.BaseStream.Position += sizeof(ushort) * padding;
                break;

            case TypeCode.Int32:
                bw.WriteInt32((int)value, bits);
                bw.BaseStream.Position += sizeof(int) * padding;
                break;

            case TypeCode.UInt32:
                bw.WriteUInt32((uint)value, bits);
                bw.BaseStream.Position += sizeof(uint) * padding;
                break;

            case TypeCode.Int64:
                bw.WriteInt64((long)value, bits);
                bw.BaseStream.Position += sizeof(long) * padding;
                break;

            case TypeCode.UInt64:
                bw.WriteUInt64((ulong)value, bits);
                bw.BaseStream.Position += sizeof(ulong) * padding;
                break;

            case TypeCode.Single:
                bw.Write((float)value);
                bw.BaseStream.Position += sizeof(float) * padding;
                break;

            case TypeCode.String:
                if (entry.Header.HasOffsetTable)
                {
                    bw.Write(Encoding.UTF8.GetBytes(value.ToString()));
                    bw.Write((byte)0);
                }
                else
                {
                    bw.Write(st.Write(value.ToString(), duplicates));
                }
                break;

            default:
                throw new Exception($"Unknown TypeCode {value.GetType().Name}");
            }
        }
Example #13
0
        private static object ReadValue <T>(BinaryReader dbReader, DBEntry <T> entry, TypeCode type, uint padding, Dictionary <int, string> StringTable, FieldStructureEntry bits) where T : class
        {
            object value;

            switch (type)
            {
            case TypeCode.Boolean:
                value = dbReader.ReadBoolean();
                dbReader.BaseStream.Position += sizeof(bool) * padding;
                break;

            case TypeCode.SByte:
                value = dbReader.ReadSByte();
                dbReader.BaseStream.Position += sizeof(sbyte) * padding;
                break;

            case TypeCode.Byte:
                value = dbReader.ReadByte();
                dbReader.BaseStream.Position += sizeof(byte) * padding;
                break;

            case TypeCode.Int16:
                value = dbReader.ReadInt16();
                dbReader.BaseStream.Position += sizeof(short) * padding;
                break;

            case TypeCode.UInt16:
                value = dbReader.ReadUInt16();
                dbReader.BaseStream.Position += sizeof(ushort) * padding;
                break;

            case TypeCode.Int32:
                value = dbReader.ReadInt32(bits);
                dbReader.BaseStream.Position += sizeof(int) * padding;
                break;

            case TypeCode.UInt32:
                value = dbReader.ReadUInt32(bits);
                dbReader.BaseStream.Position += sizeof(uint) * padding;
                break;

            case TypeCode.Int64:
                value = dbReader.ReadInt64(bits);
                dbReader.BaseStream.Position += sizeof(long) * padding;
                break;

            case TypeCode.UInt64:
                value = dbReader.ReadUInt64(bits);
                dbReader.BaseStream.Position += sizeof(ulong) * padding;
                break;

            case TypeCode.Single:
                value = dbReader.ReadSingle();
                dbReader.BaseStream.Position += sizeof(float) * padding;
                break;

            case TypeCode.String:
                if (entry.Header.IsTypeOf <WDB>() || entry.Header.IsTypeOf <HTFX>() || entry.Header.HasOffsetTable)
                {
                    value = dbReader.ReadStringNull();
                }
                else
                {
                    int stindex = dbReader.ReadInt32();
                    if (!StringTable.ContainsKey(stindex))
                    {
                        throw new Exception("Strings not found in string table");
                    }

                    value = StringTable[stindex];
                }
                break;

            default:
                throw new Exception($"Unknown TypeCode");
            }

            return(value);
        }