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); }
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); } }