118 lines
3.8 KiB
C#
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();
|
|
}
|
|
}
|
|
} |