-
Notifications
You must be signed in to change notification settings - Fork 69
Expand file tree
/
Copy pathBinaryFileHelper.cs
More file actions
122 lines (105 loc) · 4.16 KB
/
Copy pathBinaryFileHelper.cs
File metadata and controls
122 lines (105 loc) · 4.16 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
using System;
using System.IO;
using System.Text;
namespace UnityDataTools.Analyzer.Util;
/// <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 uint ReadUInt32(BinaryReader reader, bool swap)
{
uint raw = reader.ReadUInt32();
return swap ? SwapUInt32(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);
}
}