コード例 #1
0
ファイル: WDC2Reader.cs プロジェクト: coolzoom/WDBXEditor2-1
        public WDC2Reader(Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.UTF8))
            {
                if (reader.BaseStream.Length < HeaderSize)
                {
                    throw new InvalidDataException("WDC2 file is corrupted!");
                }

                uint magic = reader.ReadUInt32();

                if (magic != WDC2FmtSig && magic != CLS1FmtSig)
                {
                    throw new InvalidDataException("WDC2 file is corrupted!");
                }

                Signature       = magic;
                RecordsCount    = reader.ReadInt32();
                FieldsCount     = reader.ReadInt32();
                RecordSize      = reader.ReadInt32();
                StringTableSize = reader.ReadInt32();
                TableHash       = reader.ReadUInt32();
                LayoutHash      = reader.ReadUInt32();
                MinIndex        = reader.ReadInt32();
                MaxIndex        = reader.ReadInt32();
                int locale = reader.ReadInt32();
                Flags        = (DB2Flags)reader.ReadUInt16();
                IdFieldIndex = reader.ReadUInt16();
                int totalFieldsCount = reader.ReadInt32();
                PackedDataOffset = reader.ReadInt32();        // Offset within the field where packed data starts
                int lookupColumnCount  = reader.ReadInt32();  // count of lookup columns
                int columnMetaDataSize = reader.ReadInt32();  // 24 * NumFields bytes, describes column bit packing, {ushort recordOffset, ushort size, uint additionalDataSize, uint compressionType, uint packedDataOffset or commonvalue, uint cellSize, uint cardinality}[NumFields], sizeof(DBC2CommonValue) == 8
                int commonDataSize     = reader.ReadInt32();
                int palletDataSize     = reader.ReadInt32();  // in bytes, sizeof(DBC2PalletValue) == 4
                int sectionsCount      = reader.ReadInt32();

                if (sectionsCount > 1)
                {
                    throw new Exception("WDC2 only supports 1 section");
                }

                if (sectionsCount == 0 || RecordsCount == 0)
                {
                    return;
                }

                var sections = reader.ReadArray <SectionHeader>(sectionsCount).ToList();
                m_sections = sections.OfType <IEncryptableDatabaseSection>().ToList();

                // field meta data
                field_structure_data = reader.ReadArray <FieldMetaData>(FieldsCount);

                // column meta data
                ColumnMeta = reader.ReadArray <ColumnMetaData>(FieldsCount);

                // pallet data
                PalletData = new Value32[ColumnMeta.Length][];
                for (int i = 0; i < ColumnMeta.Length; i++)
                {
                    if (ColumnMeta[i].CompressionType == CompressionType.Pallet || ColumnMeta[i].CompressionType == CompressionType.PalletArray)
                    {
                        PalletData[i] = reader.ReadArray <Value32>((int)ColumnMeta[i].AdditionalDataSize / 4);
                    }
                }

                // common data
                CommonData = new Dictionary <int, Value32> [ColumnMeta.Length];
                for (int i = 0; i < ColumnMeta.Length; i++)
                {
                    if (ColumnMeta[i].CompressionType == CompressionType.Common)
                    {
                        var commonValues = new Dictionary <int, Value32>((int)ColumnMeta[i].AdditionalDataSize / 8);
                        CommonData[i] = commonValues;

                        for (int j = 0; j < ColumnMeta[i].AdditionalDataSize / 8; j++)
                        {
                            commonValues[reader.ReadInt32()] = reader.Read <Value32>();
                        }
                    }
                }

                for (int sectionIndex = 0; sectionIndex < sectionsCount; sectionIndex++)
                {
                    reader.BaseStream.Position = sections[sectionIndex].FileOffset;

                    if (!Flags.HasFlagExt(DB2Flags.Sparse))
                    {
                        // records data
                        RecordsData = reader.ReadBytes(sections[sectionIndex].NumRecords * RecordSize);

                        Array.Resize(ref RecordsData, RecordsData.Length + 8); // pad with extra zeros so we don't crash when reading

                        // string data
                        StringTable = new Dictionary <long, string>(sections[sectionIndex].StringTableSize / 0x20);
                        for (int i = 0; i < sections[sectionIndex].StringTableSize;)
                        {
                            long oldPos = reader.BaseStream.Position;
                            StringTable[oldPos] = reader.ReadCString();
                            i += (int)(reader.BaseStream.Position - oldPos);
                        }
                    }
                    else
                    {
                        // sparse data with inlined strings
                        RecordsData = reader.ReadBytes(sections[sectionIndex].SparseTableOffset - sections[sectionIndex].FileOffset);

                        if (reader.BaseStream.Position != sections[sectionIndex].SparseTableOffset)
                        {
                            throw new Exception("reader.BaseStream.Position != sections[sectionIndex].SparseTableOffset");
                        }

                        int sparseCount = MaxIndex - MinIndex + 1;

                        offset_map_Entries = new List <offset_map_entry>(sparseCount);
                        CopyData           = new Dictionary <int, int>(sparseCount);
                        var sparseIdLookup = new Dictionary <uint, int>(sparseCount);

                        for (int i = 0; i < sparseCount; i++)
                        {
                            offset_map_entry sparse = reader.Read <offset_map_entry>();
                            if (sparse.Offset == 0 || sparse.Size == 0)
                            {
                                continue;
                            }

                            if (sparseIdLookup.TryGetValue(sparse.Offset, out int copyId))
                            {
                                CopyData[MinIndex + i] = copyId;
                            }
                            else
                            {
                                offset_map_Entries.Add(sparse);
                                sparseIdLookup.Add(sparse.Offset, MinIndex + i);
                            }
                        }
                    }

                    // index data
                    id_list_data = reader.ReadArray <int>(sections[sectionIndex].IndexDataSize / 4);

                    // fix zero-filled index data
                    if (id_list_data.Length > 0 && id_list_data.All(x => x == 0))
                    {
                        id_list_data = Enumerable.Range(MinIndex, MaxIndex - MinIndex + 1).ToArray();
                    }

                    // duplicate rows data
                    if (CopyData == null)
                    {
                        CopyData = new Dictionary <int, int>(sections[sectionIndex].CopyTableSize / 8);
                    }

                    for (int i = 0; i < sections[sectionIndex].CopyTableSize / 8; i++)
                    {
                        CopyData[reader.ReadInt32()] = reader.ReadInt32();
                    }

                    // reference data
                    ReferenceData refData = new ReferenceData();
                    if (sections[sectionIndex].ParentLookupDataSize > 0)
                    {
                        refData.NumRecords = reader.ReadInt32();
                        refData.MinId      = reader.ReadInt32();
                        refData.MaxId      = reader.ReadInt32();

                        var entries = reader.ReadArray <ReferenceEntry>(refData.NumRecords);
                        for (int i = 0; i < entries.Length; i++)
                        {
                            refData.Entries[entries[i].Index] = entries[i].Id;
                        }
                    }

                    int position = 0;
                    for (int i = 0; i < RecordsCount; i++)
                    {
                        BitReader bitReader = new BitReader(RecordsData)
                        {
                            Position = 0
                        };

                        if (Flags.HasFlagExt(DB2Flags.Sparse))
                        {
                            bitReader.Position = position;
                            position          += offset_map_Entries[i].Size * 8;
                        }
                        else
                        {
                            bitReader.Offset = i * RecordSize;
                        }

                        refData.Entries.TryGetValue(i, out int refId);

                        IDBRow rec = new WDC2Row(this, bitReader, sections[sectionIndex].FileOffset, sections[sectionIndex].IndexDataSize != 0 ? id_list_data[i] : -1, refId, i);
                        _Records.Add(i, rec);
                    }
                }
            }
        }
コード例 #2
0
ファイル: WDB5Reader.cs プロジェクト: coolzoom/WDBXEditor2-1
        public WDB5Reader(Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.UTF8))
            {
                if (reader.BaseStream.Length < HeaderSize)
                {
                    throw new InvalidDataException("WDB5 file is corrupted!");
                }

                uint magic = reader.ReadUInt32();

                if (magic != WDB5FmtSig)
                {
                    throw new InvalidDataException("WDB5 file is corrupted!");
                }

                RecordsCount    = reader.ReadInt32();
                FieldsCount     = reader.ReadInt32();
                RecordSize      = reader.ReadInt32();
                StringTableSize = reader.ReadInt32();
                TableHash       = reader.ReadUInt32();
                LayoutHash      = reader.ReadUInt32();
                MinIndex        = reader.ReadInt32();
                MaxIndex        = reader.ReadInt32();
                int locale        = reader.ReadInt32();
                int copyTableSize = reader.ReadInt32();
                Flags        = (DB2Flags)reader.ReadUInt16();
                IdFieldIndex = reader.ReadUInt16();

                if (RecordsCount == 0)
                {
                    return;
                }

                // field meta data
                field_structure_data = reader.ReadArray <FieldMetaData>(FieldsCount);

                if (!Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    // records data
                    RecordsData = reader.ReadBytes(RecordsCount * RecordSize);
                    Array.Resize(ref RecordsData, RecordsData.Length + 8); // pad with extra zeros so we don't crash when reading

                    // string table
                    StringTable = new Dictionary <long, string>(StringTableSize / 0x20);
                    for (int i = 0; i < StringTableSize;)
                    {
                        long oldPos = reader.BaseStream.Position;
                        StringTable[i] = reader.ReadCString();
                        i += (int)(reader.BaseStream.Position - oldPos);
                    }
                }
                else
                {
                    // sparse data with inlined strings
                    RecordsData = reader.ReadBytes(StringTableSize - (int)reader.BaseStream.Position);

                    int sparseCount = MaxIndex - MinIndex + 1;

                    offset_map_Entries = new List <offset_map_entry>(sparseCount);
                    CopyData           = new Dictionary <int, int>(sparseCount);
                    var sparseIdLookup = new Dictionary <uint, int>(sparseCount);

                    for (int i = 0; i < sparseCount; i++)
                    {
                        offset_map_entry sparse = reader.Read <offset_map_entry>();
                        if (sparse.Offset == 0 || sparse.Size == 0)
                        {
                            continue;
                        }

                        if (sparseIdLookup.TryGetValue(sparse.Offset, out int copyId))
                        {
                            CopyData[MinIndex + i] = copyId;
                        }
                        else
                        {
                            offset_map_Entries.Add(sparse);
                            sparseIdLookup.Add(sparse.Offset, MinIndex + i);
                        }
                    }
                }

                // secondary key
                if (Flags.HasFlagExt(DB2Flags.SecondaryKey))
                {
                    ForeignKeyData = reader.ReadArray <int>(MaxIndex - MinIndex + 1);
                }

                // index table
                if (Flags.HasFlagExt(DB2Flags.Index))
                {
                    id_list_data = reader.ReadArray <int>(RecordsCount);
                }

                // duplicate rows data
                if (CopyData == null)
                {
                    CopyData = new Dictionary <int, int>(copyTableSize / 8);
                }

                for (int i = 0; i < copyTableSize / 8; i++)
                {
                    CopyData[reader.ReadInt32()] = reader.ReadInt32();
                }

                int position = 0;
                for (int i = 0; i < RecordsCount; i++)
                {
                    BitReader bitReader = new BitReader(RecordsData)
                    {
                        Position = 0
                    };

                    if (Flags.HasFlagExt(DB2Flags.Sparse))
                    {
                        bitReader.Position = position;
                        position          += offset_map_Entries[i].Size * 8;
                    }
                    else
                    {
                        bitReader.Offset = i * RecordSize;
                    }

                    IDBRow rec = new WDB5Row(this, bitReader, Flags.HasFlagExt(DB2Flags.Index) ? id_list_data[i] : -1, i);
                    _Records.Add(i, rec);
                }
            }
        }
コード例 #3
0
ファイル: WDB6Reader.cs プロジェクト: coolzoom/WDBXEditor2-1
        public unsafe WDB6Reader(Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.UTF8))
            {
                if (reader.BaseStream.Length < HeaderSize)
                {
                    throw new InvalidDataException("WDB6 file is corrupted!");
                }

                uint magic = reader.ReadUInt32();

                if (magic != WDB6FmtSig)
                {
                    throw new InvalidDataException("WDB6 file is corrupted!");
                }

                RecordsCount    = reader.ReadInt32();
                FieldsCount     = reader.ReadInt32();
                RecordSize      = reader.ReadInt32();
                StringTableSize = reader.ReadInt32();
                TableHash       = reader.ReadUInt32();
                LayoutHash      = reader.ReadUInt32();
                MinIndex        = reader.ReadInt32();
                MaxIndex        = reader.ReadInt32();
                int locale        = reader.ReadInt32();
                int copyTableSize = reader.ReadInt32();
                Flags        = (DB2Flags)reader.ReadUInt16();
                IdFieldIndex = reader.ReadUInt16();
                int totalFieldCount = reader.ReadInt32();
                int commonDataSize  = reader.ReadInt32();

                if (RecordsCount == 0)
                {
                    return;
                }

                // field meta data
                field_structure_data = reader.ReadArray <FieldMetaData>(FieldsCount);

                if (!Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    // records data
                    RecordsData = reader.ReadBytes(RecordsCount * RecordSize);
                    Array.Resize(ref RecordsData, RecordsData.Length + 8); // pad with extra zeros so we don't crash when reading

                    // string table
                    StringTable = new Dictionary <long, string>(StringTableSize / 0x20);
                    for (int i = 0; i < StringTableSize;)
                    {
                        long oldPos = reader.BaseStream.Position;
                        StringTable[i] = reader.ReadCString();
                        i += (int)(reader.BaseStream.Position - oldPos);
                    }
                }
                else
                {
                    // sparse data with inlined strings
                    RecordsData = reader.ReadBytes(StringTableSize - (int)reader.BaseStream.Position);

                    int sparseCount = MaxIndex - MinIndex + 1;

                    offset_map_Entries = new List <offset_map_entry>(sparseCount);
                    CopyData           = new Dictionary <int, int>(sparseCount);
                    var sparseIdLookup = new Dictionary <uint, int>(sparseCount);

                    for (int i = 0; i < sparseCount; i++)
                    {
                        offset_map_entry sparse = reader.Read <offset_map_entry>();
                        if (sparse.Offset == 0 || sparse.Size == 0)
                        {
                            continue;
                        }

                        if (sparseIdLookup.TryGetValue(sparse.Offset, out int copyId))
                        {
                            CopyData[MinIndex + i] = copyId;
                        }
                        else
                        {
                            offset_map_Entries.Add(sparse);
                            sparseIdLookup.Add(sparse.Offset, MinIndex + i);
                        }
                    }
                }

                // secondary key
                if (Flags.HasFlagExt(DB2Flags.SecondaryKey))
                {
                    ForeignKeyData = reader.ReadArray <int>(MaxIndex - MinIndex + 1);
                }

                // index table
                if (Flags.HasFlagExt(DB2Flags.Index))
                {
                    id_list_data = reader.ReadArray <int>(RecordsCount);
                }

                // duplicate rows data
                if (CopyData == null)
                {
                    CopyData = new Dictionary <int, int>(copyTableSize / 8);
                }

                for (int i = 0; i < copyTableSize / 8; i++)
                {
                    CopyData[reader.ReadInt32()] = reader.ReadInt32();
                }

                if (commonDataSize > 0)
                {
                    Array.Resize(ref field_structure_data, totalFieldCount);

                    int fieldCount = reader.ReadInt32();
                    CommonData = new Dictionary <int, Value32> [fieldCount];

                    // HACK as of 24473 values are 4 byte aligned
                    // try to calculate this by seeing if all <id, value> tuples are 8 bytes
                    CommonDataIsAligned = (commonDataSize - 4 - (fieldCount * 5)) % 8 == 0;
                    CommonDataTypes     = new byte[totalFieldCount - FieldsCount];

                    for (int i = 0; i < fieldCount; i++)
                    {
                        int  count = reader.ReadInt32();
                        byte type  = reader.ReadByte();
                        int  size  = CommonDataIsAligned ? 4 : (32 - CommonTypeBits[type]) >> 3;

                        // add the new meta entry
                        if (i > FieldsCount)
                        {
                            CommonDataTypes[i - FieldsCount] = type;

                            field_structure_data[i] = new FieldMetaData()
                            {
                                Bits   = CommonTypeBits[type],
                                Offset = (short)(field_structure_data[i - 1].Offset + ((32 - field_structure_data[i - 1].Bits) >> 3))
                            };
                        }

                        var commonValues = new Dictionary <int, Value32>(count);
                        for (int j = 0; j < count; j++)
                        {
                            int     id     = reader.ReadInt32();
                            byte[]  buffer = reader.ReadBytes(size);
                            Value32 value  = Unsafe.ReadUnaligned <Value32>(ref buffer[0]);

                            commonValues.Add(id, value);
                        }

                        CommonData[i] = commonValues;
                    }
                }

                int position = 0;
                for (int i = 0; i < RecordsCount; i++)
                {
                    BitReader bitReader = new BitReader(RecordsData)
                    {
                        Position = 0
                    };

                    if (Flags.HasFlagExt(DB2Flags.Sparse))
                    {
                        bitReader.Position = position;
                        position          += offset_map_Entries[i].Size * 8;
                    }
                    else
                    {
                        bitReader.Offset = i * RecordSize;
                    }

                    IDBRow rec = new WDB6Row(this, bitReader, Flags.HasFlagExt(DB2Flags.Index) ? id_list_data[i] : -1, i);
                    _Records.Add(i, rec);
                }
            }
        }