Files
parkan-playground/MshLib/Msh0x0A.cs
T

67 lines
1.9 KiB
C#
Raw Permalink Normal View History

2025-08-26 04:29:30 +03:00
using System.Buffers.Binary;
using System.Text;
using NResLib;
2026-05-17 15:40:16 +03:00
namespace MshLib;
2025-08-26 04:29:30 +03:00
2026-05-09 20:36:43 +03:00
/// <summary>
/// MSH-компонент 0x0A: строки узлов.
/// У FParkan: Res10 / Node strings. Старое локальное имя: ExternalRefs.
/// </summary>
public class Msh0x0A
2025-08-26 04:29:30 +03:00
{
public static List<string> ReadComponent(FileStream mshFs, NResArchive archive)
{
var aFileEntry = archive.Files.FirstOrDefault(x => x.FileType == "0A 00 00 00");
if (aFileEntry is null)
{
throw new Exception("Archive doesn't contain 0A component");
}
var data = new byte[aFileEntry.FileLength];
mshFs.Seek(aFileEntry.OffsetInFile, SeekOrigin.Begin);
mshFs.ReadExactly(data, 0, data.Length);
int pos = 0;
var strings = new List<string>();
while (pos < data.Length)
{
2026-05-09 20:36:43 +03:00
if (pos + 4 > data.Length)
{
throw new Exception("Node strings component (0x0A) has truncated length prefix");
}
2025-08-26 04:29:30 +03:00
var len = BinaryPrimitives.ReadInt32LittleEndian(data.AsSpan(pos));
2026-05-09 20:36:43 +03:00
if (len < 0 || pos + 4 + len > data.Length)
{
throw new Exception("Node strings component (0x0A) has invalid string length");
}
2025-08-26 04:29:30 +03:00
if (len == 0)
{
2026-05-09 20:36:43 +03:00
pos += 4;
strings.Add("");
2025-08-26 04:29:30 +03:00
}
else
{
var strBytes = data.AsSpan(pos + 4, len);
2026-05-09 20:36:43 +03:00
var str = Encoding.ASCII.GetString(strBytes);
2025-08-26 04:29:30 +03:00
strings.Add(str);
2026-05-09 20:36:43 +03:00
pos += len + 4;
if (pos < data.Length && data[pos] == 0)
{
pos++;
}
2025-08-26 04:29:30 +03:00
}
}
if (strings.Count != aFileEntry.ElementCount)
{
throw new Exception("String count mismatch in 0A component");
}
return strings;
}
2026-05-09 20:36:43 +03:00
}