private const uint DBCFmtSig = 0x43424457; // WDBC public DBC(string filename) { if (!CASC.Initialized) { return; } if (!CASC.FileExists(filename)) { return; } #region Read DBC using (var br = new BinaryReader(CASC.OpenFile(filename))) { // Make sure we've got a valid DBC if (br.BaseStream.Length < DBCHeader.Size) { return; } if (DBCFmtSig != br.ReadUInt32()) { return; } // Read DBC header Header = new DBCHeader(); Header.Read(br); // Read strings to a table var readPos = br.BaseStream.Position; var strTableOffset = br.BaseStream.Position + (Header.RecordCount * Header.RecordSize); br.BaseStream.Position = strTableOffset; var strTable = new Dictionary <int, string>(); while (br.BaseStream.Position < br.BaseStream.Length) { var idx = (int)(br.BaseStream.Position - strTableOffset); strTable[idx] = br.ReadCString(); } // Move back to where we were br.BaseStream.Position = readPos; Rows = new T[Header.RecordCount]; var tProperties = typeof(T).GetProperties(); for (int i = 0; i < Header.RecordCount; i++) { var row = new T(); var startPos = br.BaseStream.Position; // Can't we use a foreach here? for (int j = 0; j < tProperties.Length; j++) { switch (Type.GetTypeCode(tProperties[j].PropertyType)) { case TypeCode.Int32: tProperties[j].SetValue(row, br.ReadInt32()); break; case TypeCode.UInt32: tProperties[j].SetValue(row, br.ReadUInt32()); break; case TypeCode.Single: tProperties[j].SetValue(row, br.ReadSingle()); break; case TypeCode.String: tProperties[j].SetValue(row, strTable[br.ReadInt32()]); break; default: Console.WriteLine("wat?? {0}", Type.GetTypeCode(tProperties[j].PropertyType)); break; } } var diffSize = (br.BaseStream.Position - startPos); if (diffSize > Header.RecordSize) { return; // We read too much! Struct is wrong } if (diffSize < Header.RecordSize) { br.ReadBytes((int)(Header.RecordSize - diffSize)); // We read too little! Let's pad! } Rows[i] = row; } } #endregion }
private const uint DBCFmtSig = 0x43424457; // WDBC public DBC(string filename, BackgroundWorker worker = null) { if (!CASC.Initialized) { return; } if (!CASC.FileExists(filename)) { return; } #region Read DBC using (var br = new BinaryReader(CASC.OpenFile(filename))) { // Make sure we've got a valid DBC if (br.BaseStream.Length < DBCHeader.Size) { return; } if (DBCFmtSig != br.ReadUInt32()) { return; } // Read DBC header Header = new DBCHeader(); Header.Read(br); // Read strings to a table var readPos = br.BaseStream.Position; var strTableOffset = br.BaseStream.Position + (Header.RecordCount * Header.RecordSize); br.BaseStream.Position = strTableOffset; var strTable = new Dictionary <int, string>(); while (br.BaseStream.Position < br.BaseStream.Length) { var idx = (int)(br.BaseStream.Position - strTableOffset); strTable[idx] = br.ReadCString(); } // Move back to where we were br.BaseStream.Position = readPos; Debug.Assert(Marshal.SizeOf(typeof(T)) == Header.RecordSize, $"Invalid record size, got {Marshal.SizeOf(typeof(T))}, expected {Header.RecordSize}."); Rows = new T[Header.RecordCount]; var tProperties = typeof(T).GetProperties(); for (var i = 0; i < Header.RecordCount; i++) { var row = new T(); var startPos = br.BaseStream.Position; foreach (var prop in tProperties) { switch (Type.GetTypeCode(prop.PropertyType)) { case TypeCode.Int32: prop.SetValue(row, br.ReadInt32()); break; case TypeCode.UInt32: prop.SetValue(row, br.ReadUInt32()); break; case TypeCode.Single: prop.SetValue(row, br.ReadSingle()); break; case TypeCode.String: prop.SetValue(row, strTable[br.ReadInt32()]); break; default: Console.WriteLine("wat?? {0}", Type.GetTypeCode(prop.PropertyType)); break; } } if (worker != null) { worker.ReportProgress(i * 100 / Header.RecordCount, row); } var diffSize = (br.BaseStream.Position - startPos); if (diffSize > Header.RecordSize) { return; // We read too much! Struct is wrong } if (diffSize < Header.RecordSize) { br.ReadBytes((int)(Header.RecordSize - diffSize)); // We read too little! Let's pad! } Rows[i] = row; } } #endregion }