forked from Unity-Technologies/UnityDataTools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBinaryFileHelper.cs
More file actions
142 lines (122 loc) · 4.7 KB
/
Copy pathBinaryFileHelper.cs
File metadata and controls
142 lines (122 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.IO;
using System.Text;
namespace UnityDataTools.BinaryFormat;
/// <summary>
/// A 128-bit hash stored as four 32-bit unsigned integers, matching Unity's Hash128 binary layout.
/// </summary>
public readonly struct UnityHash128
{
public uint Data0 { get; init; }
public uint Data1 { get; init; }
public uint Data2 { get; init; }
public uint Data3 { get; init; }
public bool IsZero => Data0 == 0 && Data1 == 0 && Data2 == 0 && Data3 == 0;
public override string ToString() => $"{Data0:x8}{Data1:x8}{Data2:x8}{Data3:x8}";
}
/// <summary>
/// Helpers for reading primitive types and Unity-specific data from binary streams and byte
/// arrays, with optional endianness swapping.
/// </summary>
public static class BinaryFileHelper
{
// -----------------------------------------------------------------------
// Stream / BinaryReader helpers
// -----------------------------------------------------------------------
/// <summary>Advances the stream to the next 4-byte boundary measured from <paramref name="baseOffset"/>.</summary>
public static void AlignTo4(Stream stream, long baseOffset)
{
long rel = stream.Position - baseOffset;
long aligned = (rel + 3) & ~3L;
stream.Position = baseOffset + aligned;
}
/// <summary>Reads a null-terminated ASCII string from the stream.</summary>
public static string ReadNullTermString(BinaryReader reader)
{
var sb = new StringBuilder();
byte b;
while ((b = reader.ReadByte()) != 0)
sb.Append((char)b);
return sb.ToString();
}
public static int ReadInt32(BinaryReader reader, bool swap)
{
uint raw = reader.ReadUInt32();
return (int)(swap ? SwapUInt32(raw) : raw);
}
public static short ReadInt16(BinaryReader reader, bool swap)
{
ushort raw = reader.ReadUInt16();
if (swap)
raw = (ushort)((raw << 8) | (raw >> 8));
return (short)raw;
}
public static ushort ReadUInt16(BinaryReader reader, bool swap)
{
ushort raw = reader.ReadUInt16();
if (swap)
raw = (ushort)((raw << 8) | (raw >> 8));
return raw;
}
public static uint ReadUInt32(BinaryReader reader, bool swap)
{
uint raw = reader.ReadUInt32();
return swap ? SwapUInt32(raw) : raw;
}
public static ulong ReadUInt64(BinaryReader reader, bool swap)
{
ulong raw = reader.ReadUInt64();
return swap ? SwapUInt64(raw) : raw;
}
public static long ReadInt64(BinaryReader reader, bool swap)
{
ulong raw = reader.ReadUInt64();
return (long)(swap ? SwapUInt64(raw) : raw);
}
public static UnityHash128 ReadHash128(BinaryReader reader, bool swap)
{
return new UnityHash128
{
Data0 = ReadUInt32(reader, swap),
Data1 = ReadUInt32(reader, swap),
Data2 = ReadUInt32(reader, swap),
Data3 = ReadUInt32(reader, swap),
};
}
// -----------------------------------------------------------------------
// Byte-array helpers
// -----------------------------------------------------------------------
/// <summary>Reads a UInt32 from a byte array at the specified offset, optionally swapping endianness.</summary>
public static uint ReadUInt32(byte[] buffer, int offset, bool swap)
{
uint value = BitConverter.ToUInt32(buffer, offset);
return swap ? SwapUInt32(value) : value;
}
/// <summary>Reads a UInt64 from a byte array at the specified offset, optionally swapping endianness.</summary>
public static ulong ReadUInt64(byte[] buffer, int offset, bool swap)
{
ulong value = BitConverter.ToUInt64(buffer, offset);
return swap ? SwapUInt64(value) : value;
}
// -----------------------------------------------------------------------
// Byte-swap utilities
// -----------------------------------------------------------------------
public static uint SwapUInt32(uint value)
{
return ((value & 0x000000FFU) << 24) |
((value & 0x0000FF00U) << 8) |
((value & 0x00FF0000U) >> 8) |
((value & 0xFF000000U) >> 24);
}
public static ulong SwapUInt64(ulong value)
{
return ((value & 0x00000000000000FFUL) << 56) |
((value & 0x000000000000FF00UL) << 40) |
((value & 0x0000000000FF0000UL) << 24) |
((value & 0x00000000FF000000UL) << 8) |
((value & 0x000000FF00000000UL) >> 8) |
((value & 0x0000FF0000000000UL) >> 24) |
((value & 0x00FF000000000000UL) >> 40) |
((value & 0xFF00000000000000UL) >> 56);
}
}