This commit is contained in:
@@ -11,8 +11,7 @@ public readonly unsafe ref struct GfdFileView
|
||||
private readonly ReadOnlySpan<byte> Span;
|
||||
private readonly bool DirectLookup;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="GfdFileView"/> struct.</summary>
|
||||
/// <param name="span">The data.</param>
|
||||
// span: raw .gfd file bytes
|
||||
public GfdFileView(ReadOnlySpan<byte> span)
|
||||
{
|
||||
Span = span;
|
||||
@@ -27,18 +26,13 @@ public readonly unsafe ref struct GfdFileView
|
||||
DirectLookup &= i + 1 == entries[i].Id;
|
||||
}
|
||||
|
||||
/// <summary>Gets the header.</summary>
|
||||
private ref readonly GfdHeader Header => ref MemoryMarshal.AsRef<GfdHeader>(Span);
|
||||
|
||||
/// <summary>Gets the entries.</summary>
|
||||
private ReadOnlySpan<GfdEntry> Entries =>
|
||||
MemoryMarshal.Cast<byte, GfdEntry>(Span[sizeof(GfdHeader)..]);
|
||||
|
||||
/// <summary>Attempts to get an entry.</summary>
|
||||
/// <param name="iconId">The icon ID.</param>
|
||||
/// <param name="entry">The entry.</param>
|
||||
/// <param name="followRedirect">Whether to follow redirects.</param>
|
||||
/// <returns><c>true</c> if found.</returns>
|
||||
// Returns true if the entry was found.
|
||||
// followRedirect: whether to chase redirect chains.
|
||||
public bool TryGetEntry(uint iconId, out GfdEntry entry, bool followRedirect = true)
|
||||
{
|
||||
if (iconId == 0)
|
||||
@@ -50,9 +44,8 @@ public readonly unsafe ref struct GfdFileView
|
||||
var entries = Entries;
|
||||
if (DirectLookup)
|
||||
{
|
||||
// Resolve redirects on the direct-lookup path too — the binary-search
|
||||
// path follows them, and skipping them here was inconsistent for
|
||||
// contiguous ID sets.
|
||||
// Follow redirects on the direct-lookup path for consistency with
|
||||
// the binary-search path.
|
||||
var visited = 0;
|
||||
while (iconId <= entries.Length)
|
||||
{
|
||||
@@ -107,49 +100,28 @@ public readonly unsafe ref struct GfdFileView
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Header of a .gfd file.</summary>
|
||||
// .gfd file header
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct GfdHeader
|
||||
{
|
||||
/// <summary>Signature: "gftd0100".</summary>
|
||||
public fixed byte Signature[8];
|
||||
|
||||
/// <summary>Number of entries.</summary>
|
||||
public fixed byte Signature[8]; // "gftd0100"
|
||||
public int Count;
|
||||
|
||||
/// <summary>Unused/unknown.</summary>
|
||||
public fixed byte Padding[4];
|
||||
}
|
||||
|
||||
/// <summary>An entry of a .gfd file.</summary>
|
||||
// .gfd file entry -- one icon slot
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
|
||||
public struct GfdEntry
|
||||
{
|
||||
/// <summary>ID of the entry.</summary>
|
||||
public ushort Id;
|
||||
|
||||
/// <summary>The left offset of the entry.</summary>
|
||||
public ushort Left;
|
||||
|
||||
/// <summary>The top offset of the entry.</summary>
|
||||
public ushort Top;
|
||||
|
||||
/// <summary>The width of the entry.</summary>
|
||||
public ushort Width;
|
||||
|
||||
/// <summary>The height of the entry.</summary>
|
||||
public ushort Height;
|
||||
|
||||
/// <summary>Unknown/unused.</summary>
|
||||
public ushort Unk0A;
|
||||
|
||||
/// <summary>The redirected entry, maybe.</summary>
|
||||
public ushort Redirect;
|
||||
|
||||
/// <summary>Unknown/unused.</summary>
|
||||
public ushort Redirect; // non-zero = redirects to another entry
|
||||
public ushort Unk0E;
|
||||
|
||||
/// <summary>Gets a value indicating whether this entry is effectively empty.</summary>
|
||||
public bool IsEmpty => Width == 0 || Height == 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user