Exemplo n.º 1
0
        public void WriteEndTable()
        {
            if (status == Status.FieldCollection)
            {
                WriteEndFieldCollection();
            }

            if (status == Status.Row)
            {
                WriteEndRow();
            }

            status = Status.End;

            destination.Seek(headerPosition + header.RowsPosition + (header.RowLength * header.RowCount), SeekOrigin.Begin);

            stringPool.Write(destination);
            header.StringPoolPosition = (uint)stringPool.Position - headerPosition;

            DataStream.Pad(destination, vldPool.Align);

            vldPool.Write(destination);
            header.DataPoolPosition = (uint)vldPool.Position - headerPosition;

            DataStream.Pad(destination, vldPool.Align);

            long previousPosition = destination.Position;

            header.Length = (uint)destination.Position - headerPosition;

            if (settings.EncodingType == Encoding.GetEncoding("shift-jis"))
            {
                header.EncodingType = CriTableHeader.EncodingTypeShiftJis;
            }

            else if (settings.EncodingType == Encoding.UTF8)
            {
                header.EncodingType = CriTableHeader.EncodingTypeUtf8;
            }

            destination.Seek(headerPosition, SeekOrigin.Begin);

            destination.Write(CriTableHeader.SignatureBytes, 0, 4);
            DataStream.WriteUInt32BE(destination, header.Length - 8);
            DataStream.WriteByte(destination, header.UnknownByte);
            DataStream.WriteByte(destination, header.EncodingType);
            DataStream.WriteUInt16BE(destination, (ushort)(header.RowsPosition - 8));
            DataStream.WriteUInt32BE(destination, header.StringPoolPosition - 8);
            DataStream.WriteUInt32BE(destination, header.DataPoolPosition - 8);
            DataStream.WriteUInt32BE(destination, header.TableNamePosition);
            DataStream.WriteUInt16BE(destination, header.FieldCount);
            DataStream.WriteUInt16BE(destination, header.RowLength);
            DataStream.WriteUInt32BE(destination, header.RowCount);

            if (settings.EnableMask)
            {
                destination.Seek(headerPosition, SeekOrigin.Begin);
                CriTableMasker.Mask(destination, header.Length, settings.MaskXor, settings.MaskXorMultiplier);
            }

            destination.Seek(previousPosition, SeekOrigin.Begin);
        }
Exemplo n.º 2
0
        private void ReadTable()
        {
            headerPosition = source.Position;

            if (!(header.Signature = DataStream.ReadBytes(source, 4)).SequenceEqual(CriTableHeader.SignatureBytes))
            {
                MemoryStream unmaskedSource = new MemoryStream();

                CriTableMasker.FindKeys(header.Signature, out uint x, out uint m);

                source.Seek(headerPosition, SeekOrigin.Begin);
                CriTableMasker.Mask(source, unmaskedSource, source.Length, x, m);

                // Close the old stream
                if (!leaveOpen)
                {
                    source.Close();
                }

                source = unmaskedSource;
                source.Seek(4, SeekOrigin.Begin);
            }

            header.Length       = DataStream.ReadUInt32BE(source) + 0x8;
            header.UnknownByte  = DataStream.ReadByte(source);
            header.EncodingType = DataStream.ReadByte(source);

            if (header.UnknownByte != 0)
            {
                throw new InvalidDataException($"Invalid byte ({header.UnknownByte}. Please report this error with the file(s).");
            }

            switch (header.EncodingType)
            {
            case CriTableHeader.EncodingTypeShiftJis:
                encoding = Encoding.GetEncoding("shift-jis");
                break;

            case CriTableHeader.EncodingTypeUtf8:
                encoding = Encoding.UTF8;
                break;

            default:
                throw new InvalidDataException($"Unknown encoding type ({header.EncodingType}). Please report this error with the file(s).");
            }

            header.RowsPosition       = (ushort)(DataStream.ReadUInt16BE(source) + 0x8);
            header.StringPoolPosition = DataStream.ReadUInt32BE(source) + 0x8;
            header.DataPoolPosition   = DataStream.ReadUInt32BE(source) + 0x8;
            header.TableName          = ReadString();
            header.FieldCount         = DataStream.ReadUInt16BE(source);
            header.RowLength          = DataStream.ReadUInt16BE(source);
            header.RowCount           = DataStream.ReadUInt32BE(source);

            uint offset = 0;

            for (ushort i = 0; i < header.FieldCount; i++)
            {
                CriTableField field = new CriTableField();
                field.Flag = (CriFieldFlag)DataStream.ReadByte(source);

                if (field.Flag.HasFlag(CriFieldFlag.Name))
                {
                    field.Name = ReadString();
                }

                if (field.Flag.HasFlag(CriFieldFlag.DefaultValue))
                {
                    if (field.Flag.HasFlag(CriFieldFlag.Data))
                    {
                        field.Position = DataStream.ReadUInt32BE(source);
                        field.Length   = DataStream.ReadUInt32BE(source);
                    }

                    else
                    {
                        field.Value = ReadValue(field.Flag);
                    }
                }

                // Not even per row, and not even constant value? Then there's no storage.
                else if (!field.Flag.HasFlag(CriFieldFlag.RowStorage) && !field.Flag.HasFlag(CriFieldFlag.DefaultValue))
                {
                    field.Value = CriField.NullValues[(byte)field.Flag & 0x0F];
                }

                // Row storage, calculate the offset
                if (field.Flag.HasFlag(CriFieldFlag.RowStorage))
                {
                    field.Offset = offset;

                    switch (field.Flag & CriFieldFlag.TypeMask)
                    {
                    case CriFieldFlag.Byte:
                    case CriFieldFlag.SByte:
                        offset += 1;
                        break;

                    case CriFieldFlag.Int16:
                    case CriFieldFlag.UInt16:
                        offset += 2;
                        break;

                    case CriFieldFlag.Int32:
                    case CriFieldFlag.UInt32:
                    case CriFieldFlag.Single:
                    case CriFieldFlag.String:
                        offset += 4;
                        break;

                    case CriFieldFlag.Int64:
                    case CriFieldFlag.UInt64:
                    case CriFieldFlag.Double:
                    case CriFieldFlag.Data:
                        offset += 8;
                        break;
                    }
                }

                fields.Add(field);
            }
        }