using System; using System.IO; namespace NW4RTools { public class OutputStream { // TODO: look into making this (and InputStream) inherit from Stream, or something public readonly ByteEndian Endian; private readonly bool MustReverseArrays; private readonly System.IO.MemoryStream BaseStream; public int Position { get { return (int)BaseStream.Position; } } public byte[] GetBuffer() { return BaseStream.ToArray(); } public OutputStream() { BaseStream = new MemoryStream(); Endian = ByteEndian.BigEndian; MustReverseArrays = BitConverter.IsLittleEndian; } public OutputStream(ByteEndian endian) { BaseStream = new MemoryStream(); Endian = endian; if (Endian == ByteEndian.BigEndian) MustReverseArrays = BitConverter.IsLittleEndian; else MustReverseArrays = !BitConverter.IsLittleEndian; } public void Seek(int pos) { if (pos < 0 || pos > BaseStream.Length) throw new ArgumentOutOfRangeException(); BaseStream.Position = pos; } public void AlignTo(int num) { if ((Position & (num - 1)) == 0) return; for (int i = (num - (Position & (num - 1))); i != 0; i--) { WriteByte(0); } } public void AddPadding(int count) { if (count == 0) return; else if (count == 1) WriteByte(0); else for (int i = count; i != 0; i--) WriteByte(0); } public void WriteBytes(byte[] data) { BaseStream.Write(data, 0, data.Length); } private void WriteReversedBytes(byte[] data) { // TODO: figure out if this modifies the array if (MustReverseArrays) Array.Reverse(data); BaseStream.Write(data, 0, data.Length); } public void WriteByte(byte val) { BaseStream.WriteByte(val); } public void WriteSByte(sbyte val) { WriteByte(unchecked((byte)val)); } public void WriteInt16(Int16 val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteUInt16(UInt16 val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteInt32(Int32 val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteUInt32(UInt32 val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteFloat(float val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteDouble(double val) { WriteReversedBytes(BitConverter.GetBytes(val)); } public void WriteBool(bool val) { // TODO: ReadBool in InputStream WriteByte(val ? (byte)1 : (byte)0); } public void WriteColor(Color col) { WriteByte(col.r); WriteByte(col.g); WriteByte(col.b); WriteByte(col.a); } public void WriteVec2(Vec2 vec) { WriteFloat(vec.x); WriteFloat(vec.y); } public void WriteVec3(Vec3 vec) { WriteFloat(vec.x); WriteFloat(vec.y); WriteFloat(vec.z); } public void WriteMatrix(Matrix m) { WriteFloat(m.v00); WriteFloat(m.v01); WriteFloat(m.v02); WriteFloat(m.v03); WriteFloat(m.v10); WriteFloat(m.v11); WriteFloat(m.v12); WriteFloat(m.v13); WriteFloat(m.v20); WriteFloat(m.v21); WriteFloat(m.v22); WriteFloat(m.v23); } public void WriteName(string name) { byte[] encoded = System.Text.Encoding.GetEncoding("Shift_JIS").GetBytes(name); WriteInt32(encoded.Length); WriteBytes(encoded); WriteByte(0); // add 1 to the length to include the zero byte if (((encoded.Length + 1) & 3) != 0) { for (int i = 4 - ((encoded.Length + 1) & 3); i > 0; i--) { WriteByte(0); } } } } }