C# SFFV2 Lz5/Rle8 解压实现代码

class sffV2Decompress
{
	private struct LZ5_CONTROL_PACKET
	{
		public byte[] flags;
		public void fromStream(BinaryReader br)
		{
			flags = new byte[8];
			byte abyte = br.ReadByte();
			flags[7] = (byte)(((int)abyte & 128) / 128);
			flags[6] = (byte)(((int)abyte & 64) / 64);
			flags[5] = (byte)(((int)abyte & 32) / 32);
			flags[4] = (byte)(((int)abyte & 16) / 16);
			flags[3] = (byte)(((int)abyte & 8) / 8);
			flags[2] = (byte)(((int)abyte & 4) / 4);
			flags[1] = (byte)(((int)abyte & 2) / 2);
			flags[0] = (byte)((int)abyte & 1);
		}
	}

	private struct LZ5_RLE_PACKET
	{
		public byte color;
		public int numtimes;		
		public void fromStream(BinaryReader br)
		{
			byte byte1 = br.ReadByte();
			byte byte2;
			numtimes = ((int)byte1 & 224) >> 5;
			if(numtimes == 0)
			{
				byte2 = br.ReadByte();
				numtimes = (int)byte2;
				numtimes += 8;
			}
			color = (byte)((int)byte1 & 31);
		}	
	}
	private struct LZ5_LZ_PACKET
	{
		public int len;
		public int offset;
		public byte recycled;
		public byte recycled_bits_filled;		
		public void fromStream(BinaryReader br)
		{
			byte byte1 = br.ReadByte();
			byte byte2,byte3,tmp;
			len = (int)byte1 & 63;
			if(len == 0)
			{
				byte2 = br.ReadByte();
				byte3 = br.ReadByte();
				offset = ((int)byte1 & 192) * 4 + (int)byte2 + 1;
				len = (int)byte3 + 3;
			}
			else
			{
				len += 1;
				tmp = (byte)((int)byte1 & 192);
				if(recycled_bits_filled == 2)
				{
					tmp >>= 2;
				}
				if(recycled_bits_filled == 4)
				{
					tmp >>= 4;
				}
				if(recycled_bits_filled == 6)
				{
					tmp >>= 6;
				}
				recycled += tmp;
				recycled_bits_filled += 2;
				if(recycled_bits_filled < 8)
				{
					byte2 = br.ReadByte();
					offset = byte2;
				}
				if(recycled_bits_filled == 8)
				{
					offset = recycled;
					recycled = 0;
					recycled_bits_filled = 0;
				}
				offset += 1;

			}

		}
	}
	public static byte[] unRle8(byte[] src)
	{
		List<byte> ret = new List<byte>();
		MemoryStream ms = new MemoryStream(src);
		BinaryReader br = new BinaryReader(ms);
		byte ch,color;
		int len;
		ms.Seek(0, SeekOrigin.Begin);
		while(ms.Position != ms.Length)
		{
			ch = br.ReadByte();
			if(((int)ch & 192) == 64)
			{
				color = br.ReadByte();
				len = (int)ch & 63;
				for(int i = 0; i < len; i++)
				{
					ret.Add(color);
				}
			}
			else
			{
				ret.Add(ch);
			}
		}
		br.Close();
		ms.Dispose();
		return ret.ToArray();
	}

	public static byte[] unLz5(byte[] src)
	{
		List<byte> ret = new List<byte>();
		MemoryStream ms = new MemoryStream(src);
		BinaryReader br = new BinaryReader(ms);
		LZ5_CONTROL_PACKET ctrl = new LZ5_CONTROL_PACKET();
		LZ5_RLE_PACKET rle = new LZ5_RLE_PACKET();
		LZ5_LZ_PACKET lz = new LZ5_LZ_PACKET();
		List<byte> tmp = new List<Byte>();
		ms.Seek(0, SeekOrigin.Begin);
		while(ms.Position != ms.Length)
		{
			ctrl.fromStream(br);
			for(int i = 0; i < 8; i++)
			{
				if(ms.Position == ms.Length)
				{
					break;
				}
				if(ctrl.flags[i] == 0)
				{
					rle.fromStream(br);
					for(int n = 0; n < rle.numtimes; n++)
					{
						ret.Add(rle.color);
					}
				}
				else if(ctrl.flags[i] == 1)
				{
					lz.fromStream(br);
					tmp.Clear();
					for(int n = 0; n < lz.len; n++)
					{
						int offset = ret.Count - lz.offset + n;
						if(offset < ret.Count)
						{
							tmp.Add(ret[offset]);
						}
						else
						{
							break;
						}
					}
					if(tmp.Count < lz.len && tmp.Count != 0)
					{
						int count = tmp.Count;
						int len = (lz.len - count) / count;
						List<byte> tmp2 = tmp.GetRange(0, tmp.Count);
						for(int n = 0; n < len; n++)
						{
							tmp.AddRange(tmp2);
						}
						tmp.AddRange(tmp2.GetRange(0, (lz.len - count) % count));
					}
					ret.AddRange(tmp);
				}

			}

		}
		br.Close();
		ms.Close();
		return ret.ToArray();
	}

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注