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); }
/// <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); }
/// <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)); }
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]); } } }
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]); } } }
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); } }
public void SetLength(FieldStructureEntry nextField) { this.Length = Math.Max(1, (int)Math.Floor((nextField.Offset - this.Offset) / (double)this.ByteCount)); }
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); }
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 }
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}"); } }
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); }