Axibug.MHFSaveDataAutoConve.../Data/MHFCompression.cs
2025-08-13 16:52:38 +08:00

118 lines
3.8 KiB
C#

namespace Axibug.MHFSaveAutoConverter.DataStruct
{
public static class MHFCompression
{
// 文件头常量
private static readonly byte[] HeaderBytes = {
0x63, 0x6D, 0x70, 0x20, // "cmp "
0x32, 0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x33, // "20110113"
0x20, 0x20, 0x20, 0x00 // " \0"
};
public static byte[] Decompress(byte[] data)
{
// 检查文件头
if (data.Length < 16 || !data.Take(16).SequenceEqual(HeaderBytes))
{
Console.WriteLine("存档存档无需解压");
return data;
}
Console.WriteLine("存档解压");
using var outputStream = new MemoryStream();
using var reader = new BinaryReader(new MemoryStream(data));
// 跳过16字节头
reader.BaseStream.Seek(16, SeekOrigin.Begin);
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
byte currentByte = reader.ReadByte();
if (currentByte == 0x00)
{
// 读取零序列长度
int nullCount = reader.ReadByte();
// 写入相应数量的零
for (int i = 0; i < nullCount; i++)
{
outputStream.WriteByte(0x00);
}
}
else
{
// 直接写入非零字节
outputStream.WriteByte(currentByte);
}
}
return outputStream.ToArray();
}
public static byte[] Compress(byte[] data)
{
using var outputStream = new MemoryStream();
using var writer = new BinaryWriter(outputStream);
// 写入文件头
writer.Write(HeaderBytes);
using var reader = new BinaryReader(new MemoryStream(data));
int nullCount = 0;
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
byte currentByte = reader.ReadByte();
if (currentByte == 0x00)
{
nullCount++;
// 处理连续零的序列
while (nullCount < 255 && reader.BaseStream.Position < reader.BaseStream.Length)
{
byte nextByte = reader.ReadByte();
if (nextByte == 0x00)
{
nullCount++;
}
else
{
// 写入压缩标记和零计数
writer.Write((byte)0x00);
writer.Write((byte)nullCount);
// 写入遇到的非零字节
writer.Write(nextByte);
nullCount = 0;
break;
}
}
// 处理达到最大计数或文件结束的情况
if (nullCount > 0)
{
writer.Write((byte)0x00);
writer.Write((byte)Math.Min(nullCount, 255));
nullCount = 0;
}
}
else
{
// 直接写入非零字节
writer.Write(currentByte);
}
}
// 处理结尾可能的剩余零序列
if (nullCount > 0)
{
writer.Write((byte)0x00);
writer.Write((byte)nullCount);
}
return outputStream.ToArray();
}
}
}