static void Main(string[] args) { List <string> infiles = new List <string>(); Prefilter filter = Prefilter.None; Exhaustion exhaustion = Exhaustion.Standard; for (int i = 0; i < args.Length; ++i) { if (args[i] == "--filter") { ++i; filter = (Prefilter)Enum.Parse(typeof(Prefilter), args[i], true); } else if (args[i] == "--exhaustion") { ++i; exhaustion = (Exhaustion)Enum.Parse(typeof(Exhaustion), args[i], true); } else { infiles.Add(args[i]); } } if (infiles.Count == 0) { Console.WriteLine("Usage: FileCompressor [options] files"); Console.WriteLine("Options:"); Console.WriteLine(" --filter"); foreach (object e in Enum.GetValues(typeof(Prefilter))) { Console.WriteLine(" " + e.ToString()); } Console.WriteLine(" --exhaustion"); foreach (object e in Enum.GetValues(typeof(Exhaustion))) { Console.WriteLine(" " + e.ToString()); } } foreach (string infile in infiles) { string outfile = infile + "_" + filter.ToString() + "_" + exhaustion.ToString() + ".bin"; Console.WriteLine("Generating: " + outfile); Stream ms; using (var fs = new FileStream(infile, FileMode.Open, FileAccess.Read, FileShare.Read)) { ms = fs.CopyToMemory(); fs.Close(); } using (var compressed = Compress(ms, filter, exhaustion)) { using (FileStream os = new FileStream(outfile, FileMode.Create)) { compressed.Position = 0; StreamUtils.CopyStream(compressed, os); } } } }
public static Stream Compress(Stream instream, Prefilter filter, Exhaustion exhaustion) { MemoryStream outstream = new MemoryStream((int)instream.Length); uint crc = CRC.CalculateDigest(instream.CopyToByteArray(), 0, (uint)instream.Length); if (filter == Prefilter.None) { MemoryStream memorystream = new MemoryStream((int)instream.Length); instream.Position = 0; StreamUtils.CopyStream(instream, memorystream); outstream.WriteUInt8(0); // filter ID outstream.WriteUInt32(crc, EndianUtils.Endianness.LittleEndian); CompressInternalLzmaSemiOptimized(memorystream, outstream, exhaustion); return(outstream); } if (filter == Prefilter.Delta2LE_0x30Lead) { if ((instream.Length % 2) != 0 || instream.Length < 0x30) { throw new Exception("unsupported length for " + filter.ToString()); } MemoryStream filteredstream = new MemoryStream((int)instream.Length); instream.Position = 0; StreamUtils.CopyStream(instream, filteredstream, 0x30); ushort last = 0; while (instream.Position < instream.Length) { ushort curr = instream.ReadUInt16(EndianUtils.Endianness.LittleEndian); ushort diff = (ushort)(last - curr); filteredstream.WriteUInt16(diff, EndianUtils.Endianness.LittleEndian); last = curr; } outstream.WriteUInt8(1); // filter ID outstream.WriteUInt32(crc, EndianUtils.Endianness.LittleEndian); filteredstream.Position = 0; CompressInternalLzmaSemiOptimized(filteredstream, outstream, exhaustion); return(outstream); } if (filter == Prefilter.Delta4LE_0x30Lead) { if ((instream.Length % 4) != 0 || instream.Length < 0x30) { throw new Exception("unsupported length for " + filter.ToString()); } MemoryStream filteredstream = new MemoryStream((int)instream.Length); instream.Position = 0; StreamUtils.CopyStream(instream, filteredstream, 0x30); uint last = 0; while (instream.Position < instream.Length) { uint curr = instream.ReadUInt32(EndianUtils.Endianness.LittleEndian); uint diff = (uint)(last - curr); filteredstream.WriteUInt32(diff, EndianUtils.Endianness.LittleEndian); last = curr; } outstream.WriteUInt8(2); // filter ID outstream.WriteUInt32(crc, EndianUtils.Endianness.LittleEndian); filteredstream.Position = 0; CompressInternalLzmaSemiOptimized(filteredstream, outstream, exhaustion); return(outstream); } if (filter == Prefilter.Delta2LE_Deinterleaved_0x30Lead) { if ((instream.Length % 4) != 0 || instream.Length < 0x30) { throw new Exception("unsupported length for " + filter.ToString()); } MemoryStream filteredstream = new MemoryStream((int)instream.Length); instream.Position = 0; StreamUtils.CopyStream(instream, filteredstream, 0x30); long pos = instream.Position; ushort last = 0; while (instream.Position < instream.Length) { ushort curr = instream.ReadUInt16(EndianUtils.Endianness.LittleEndian); ushort diff = (ushort)(last - curr); filteredstream.WriteUInt16(diff, EndianUtils.Endianness.LittleEndian); last = curr; instream.ReadUInt16(EndianUtils.Endianness.LittleEndian); } instream.Position = pos; last = 0; while (instream.Position < instream.Length) { instream.ReadUInt16(EndianUtils.Endianness.LittleEndian); ushort curr = instream.ReadUInt16(EndianUtils.Endianness.LittleEndian); ushort diff = (ushort)(last - curr); filteredstream.WriteUInt16(diff, EndianUtils.Endianness.LittleEndian); last = curr; } outstream.WriteUInt8(3); // filter ID outstream.WriteUInt32(crc, EndianUtils.Endianness.LittleEndian); filteredstream.Position = 0; CompressInternalLzmaSemiOptimized(filteredstream, outstream, exhaustion); return(outstream); } throw new Exception("unexpected filter"); }