-
Notifications
You must be signed in to change notification settings - Fork 4
Big Endian Support + NiDataStream Fixes #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -186,7 +186,7 @@ public int Load(System.IO.Stream stream, NifFileLoadOptions options = null) | |
| Clear(); | ||
| return 1; | ||
| } | ||
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unnecessary file edit NifFile.cs. |
||
| /* | ||
| if (!(Header.Version.FileVersion >= NiVersion.ToFile(20, 2, 0, 7) && (Header.Version.UserVersion == 11 || Header.Version.UserVersion == 12))) | ||
| { | ||
|
|
@@ -195,7 +195,6 @@ public int Load(System.IO.Stream stream, NifFileLoadOptions options = null) | |
| return 2; | ||
| } | ||
| */ | ||
|
|
||
| var streamReversible = new NiStreamReversible(streamReader); | ||
|
|
||
| Blocks = new List<INiObject>(Header.BlockCount); | ||
|
|
@@ -212,6 +211,16 @@ public int Load(System.IO.Stream stream, NifFileLoadOptions options = null) | |
| blockTypeStr = nistr.Content; | ||
| } | ||
|
|
||
| int dataStreamUsage = 0; | ||
| int dataStreamAccess = 0; | ||
| if (blockTypeStr.StartsWith("NiDataStream\x01")) | ||
| { | ||
| var parts = blockTypeStr.Split('\x01'); | ||
| blockTypeStr = parts[0]; | ||
| dataStreamUsage = int.Parse(parts[1]); | ||
| dataStreamAccess = int.Parse(parts[2]); | ||
| } | ||
|
|
||
| NiObject block = null; | ||
| INiStreamable blockStreamable = null; | ||
|
|
||
|
|
@@ -236,6 +245,17 @@ public int Load(System.IO.Stream stream, NifFileLoadOptions options = null) | |
| block = blockStreamable as NiObject; | ||
| } | ||
|
|
||
| if (blockTypeStr == "NiDataStream") | ||
| { | ||
| NiDataStream dataStream = block as NiDataStream; | ||
| if (dataStream != null) | ||
| { | ||
| dataStream.Usage = (DataStreamUsage)dataStreamUsage; | ||
| dataStream.Access = (DataStreamAccess)dataStreamAccess; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| if (block != null) | ||
| Blocks.Add(block); | ||
| } | ||
|
|
@@ -315,6 +335,7 @@ public int Save(System.IO.Stream stream, NifFileSaveOptions options = null) | |
| Header.Write(streamWriter); | ||
|
|
||
| var streamReversible = new NiStreamReversible(streamWriter); | ||
|
|
||
| long blockStartPos = streamWriter.Writer.BaseStream.Position; | ||
|
|
||
| // Retrieve block sizes from stream after writing each block | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| using System; | ||
| using System.Buffers.Binary; | ||
| using System.Text; | ||
| using System.IO; | ||
|
|
||
| namespace NiflySharp.Stream | ||
| { | ||
| public class CustomBinaryReader : BinaryReader | ||
| { | ||
| public NiEndian Endian { get; set; } = NiEndian.Little; | ||
|
|
||
| public CustomBinaryReader(System.IO.Stream input) | ||
| : base(input) | ||
| { | ||
| } | ||
|
|
||
| public CustomBinaryReader(System.IO.Stream input, Encoding encoding) | ||
| : base(input, encoding) | ||
| { | ||
| } | ||
|
|
||
| public CustomBinaryReader(System.IO.Stream input, Encoding encoding, bool leaveOpen) | ||
| : base(input, encoding, leaveOpen) | ||
| { | ||
| } | ||
|
|
||
| private ReadOnlySpan<byte> ReadSpan(int byteCount) | ||
| { | ||
| byte[] buffer = new byte[byteCount]; | ||
| int read = BaseStream.Read(buffer, 0, byteCount); | ||
| if (read != byteCount) | ||
| throw new EndOfStreamException(); | ||
| return buffer; | ||
| } | ||
|
|
||
| public override short ReadInt16() | ||
| { | ||
| var span = ReadSpan(2); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadInt16BigEndian(span) | ||
| : BinaryPrimitives.ReadInt16LittleEndian(span); | ||
| } | ||
|
|
||
| public override ushort ReadUInt16() | ||
| { | ||
| var span = ReadSpan(2); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadUInt16BigEndian(span) | ||
| : BinaryPrimitives.ReadUInt16LittleEndian(span); | ||
| } | ||
|
|
||
| public override int ReadInt32() | ||
| { | ||
| var span = ReadSpan(4); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadInt32BigEndian(span) | ||
| : BinaryPrimitives.ReadInt32LittleEndian(span); | ||
| } | ||
|
|
||
| public override uint ReadUInt32() | ||
| { | ||
| var span = ReadSpan(4); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadUInt32BigEndian(span) | ||
| : BinaryPrimitives.ReadUInt32LittleEndian(span); | ||
| } | ||
|
|
||
| public override long ReadInt64() | ||
| { | ||
| var span = ReadSpan(8); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadInt64BigEndian(span) | ||
| : BinaryPrimitives.ReadInt64LittleEndian(span); | ||
| } | ||
|
|
||
| public override ulong ReadUInt64() | ||
| { | ||
| var span = ReadSpan(8); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadUInt64BigEndian(span) | ||
| : BinaryPrimitives.ReadUInt64LittleEndian(span); | ||
| } | ||
|
|
||
| public override float ReadSingle() | ||
| { | ||
| var span = ReadSpan(4); | ||
| if (Endian == NiEndian.Big) | ||
| { | ||
| byte[] reversed = span.ToArray(); | ||
| Array.Reverse(reversed); | ||
| return BitConverter.ToSingle(reversed, 0); | ||
| } | ||
| return BitConverter.ToSingle(span); | ||
| } | ||
|
|
||
| public override double ReadDouble() | ||
| { | ||
| var span = ReadSpan(8); | ||
| if (Endian == NiEndian.Big) | ||
| { | ||
| byte[] reversed = span.ToArray(); | ||
| Array.Reverse(reversed); | ||
| return BitConverter.ToDouble(reversed, 0); | ||
| } | ||
| return BitConverter.ToDouble(span); | ||
| } | ||
|
|
||
| public override Half ReadHalf() | ||
| { | ||
| var span = ReadSpan(2); | ||
| return Endian == NiEndian.Big | ||
| ? BinaryPrimitives.ReadHalfBigEndian(span) | ||
| : BinaryPrimitives.ReadHalfLittleEndian(span); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| using NiflySharp; | ||
| using System; | ||
| using System.Buffers.Binary; | ||
| using System.Text; | ||
| using System.IO; | ||
|
|
||
| namespace NiflySharp.Stream | ||
| { | ||
| public class CustomBinaryWriter : BinaryWriter | ||
| { | ||
| public NiEndian Endian { get; set; } = NiEndian.Little; | ||
|
|
||
| public CustomBinaryWriter(System.IO.Stream output) | ||
| : base(output) | ||
| { | ||
| } | ||
|
|
||
| public CustomBinaryWriter(System.IO.Stream output, Encoding encoding) | ||
| : base(output, encoding) | ||
| { | ||
| } | ||
|
|
||
| public CustomBinaryWriter(System.IO.Stream output, Encoding encoding, bool leaveOpen) | ||
| : base(output, encoding, leaveOpen) | ||
| { | ||
| } | ||
|
|
||
| protected CustomBinaryWriter() | ||
| { | ||
| } | ||
|
|
||
| private void WriteSpan(ReadOnlySpan<byte> span) | ||
| { | ||
| OutStream.Write(span); | ||
| } | ||
|
|
||
| public override void Write(short value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[2]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteInt16BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteInt16LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(ushort value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[2]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteUInt16BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteUInt16LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(int value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[4]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteInt32BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteInt32LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(uint value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[4]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteUInt32BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(long value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[8]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteInt64BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteInt64LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(ulong value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[8]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteUInt64BigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(float value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[4]; | ||
| BitConverter.TryWriteBytes(buffer, value); | ||
|
|
||
| if (Endian == NiEndian.Big) | ||
| { | ||
| buffer[0] = buffer[3]; | ||
| buffer[1] = buffer[2]; | ||
| buffer[2] = buffer[1]; | ||
| buffer[3] = buffer[0]; | ||
| } | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(double value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[8]; | ||
| BitConverter.TryWriteBytes(buffer, value); | ||
|
|
||
| if (Endian == NiEndian.Big) | ||
| { | ||
| buffer[0] = buffer[7]; | ||
| buffer[1] = buffer[6]; | ||
| buffer[2] = buffer[5]; | ||
| buffer[3] = buffer[4]; | ||
| buffer[4] = buffer[3]; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't work for reversing values. Either use |
||
| buffer[5] = buffer[2]; | ||
| buffer[6] = buffer[1]; | ||
| buffer[7] = buffer[0]; | ||
| } | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(Half value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[2]; | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteHalfBigEndian(buffer, value); | ||
| else | ||
| BinaryPrimitives.WriteHalfLittleEndian(buffer, value); | ||
|
|
||
| WriteSpan(buffer); | ||
| } | ||
|
|
||
| public override void Write(decimal value) | ||
| { | ||
| Span<byte> buffer = stackalloc byte[16]; | ||
| int[] bits = decimal.GetBits(value); | ||
| for (int i = 0; i < 4; i++) | ||
| { | ||
| if (Endian == NiEndian.Big) | ||
| BinaryPrimitives.WriteInt32BigEndian(buffer.Slice(i * 4, 4), bits[i]); | ||
| else | ||
| BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(i * 4, 4), bits[i]); | ||
| } | ||
| WriteSpan(buffer); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove using.