public static void Main(string[] args) { bool showHelp = false; bool verbose = false; OptionSet options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_dzip] input_dir+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPaths = new List <string>(); string outputPath; if (extras.Count == 1) { inputPaths.Add(extras[0]); outputPath = Path.ChangeExtension(extras[0], ".dzip"); } else { outputPath = extras[0]; inputPaths.AddRange(extras.Skip(1)); } var paths = new SortedDictionary <string, string>(); if (verbose == true) { Console.WriteLine("Finding files..."); } foreach (var relPath in inputPaths) { string inputPath = Path.GetFullPath(relPath); if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true) { inputPath = inputPath.Substring(0, inputPath.Length - 1); } foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories)) { bool hasName; string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant(); if (paths.ContainsKey(partPath) == true) { Console.WriteLine("Ignoring {0} duplicate.", partPath); continue; } paths[partPath] = fullPath; } } using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { var pkg = new PackageFile(); output.Seek(PackageFile.HeaderSize, SeekOrigin.Begin); if (verbose == true) { Console.WriteLine("Writing files to package..."); } foreach (var kvp in paths) { if (verbose == true) { Console.WriteLine(kvp.Key); } using (var input = File.OpenRead(kvp.Value)) { var entry = new Package.Entry(); entry.Name = kvp.Key; entry.TimeStamp = File.GetLastWriteTime(kvp.Value); entry.UncompressedSize = input.Length; entry.Offset = output.Position; int blockCount = (int)((entry.UncompressedSize + 0xFFFF) >> 16); // .Align(0x10000) / 0x10000; var compressedBlocks = new byte[blockCount][]; var compressedSizes = new int[blockCount]; var uncompressedBlock = new byte[0x10000]; long left = input.Length; for (int i = 0; i < blockCount; i++) { int uncompressedSize = input.Read( uncompressedBlock, 0, uncompressedBlock.Length); var lzf = new LZF(); compressedBlocks[i] = new byte[0x20000]; int compressedSize = lzf.Compress( uncompressedBlock, uncompressedSize, compressedBlocks[i], compressedBlocks[i].Length); if (compressedSize == 0) { throw new InvalidOperationException(); } compressedSizes[i] = compressedSize; } int offset = blockCount * 4; for (int i = 0; i < blockCount; i++) { output.WriteValueS32(offset); offset += compressedSizes[i]; } for (int i = 0; i < blockCount; i++) { output.Write(compressedBlocks[i], 0, compressedSizes[i]); } entry.CompressedSize = offset; pkg.Entries.Add(entry); } } if (verbose == true) { Console.WriteLine("Writing package header..."); } pkg.Serialize(output, output.Length); } }
public void Deserialize(Stream input, ulong?decryptKey) { if (input.ReadValueU32() != 0x50495A44) // DZIP { throw new FormatException("bad magic"); } this.Version = input.ReadValueU32(); if (this.Version < 2) { throw new FormatException("unsupported version"); } var entryCount = input.ReadValueU32(); /*var unknown =*/ input.ReadValueU32(); var entryTableOffset = input.ReadValueS64(); var entryTableHash = input.ReadValueU64(); input.Seek(entryTableOffset, SeekOrigin.Begin); this.Entries.Clear(); for (uint i = 0; i < entryCount; i++) { var entry = new Package.Entry(); var length = input.ReadValueU16(); if (decryptKey.HasValue == false) { entry.Name = input.ReadString( length, true, Encoding.ASCII); } else { var nameBytes = new byte[length]; input.Read(nameBytes, 0, nameBytes.Length); for (int j = 0; j < nameBytes.Length; j++) { nameBytes[j] ^= (byte)(decryptKey >> j % 8); decryptKey *= 0x00000100000001B3UL; } using (var nameStream = new MemoryStream(nameBytes)) { entry.Name = nameStream.ReadString( length, true, Encoding.ASCII); } } //entry.TimeStamp = input.ReadValueS64(); entry.TimeStamp = DateTime.FromFileTime( input.ReadValueS64()); entry.UncompressedSize = input.ReadValueS64(); entry.Offset = input.ReadValueS64(); entry.CompressedSize = input.ReadValueS64(); this.Entries.Add(entry); } if (this.EntriesHash != entryTableHash) { throw new FormatException("bad entry table hash (wrong cdkey for DLC archives?)"); } }
public static void Main(string[] args) { bool showHelp = false; bool verbose = false; OptionSet options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List<string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_dzip] input_dir+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPaths = new List<string>(); string outputPath; if (extras.Count == 1) { inputPaths.Add(extras[0]); outputPath = Path.ChangeExtension(extras[0], ".dzip"); } else { outputPath = extras[0]; inputPaths.AddRange(extras.Skip(1)); } var paths = new SortedDictionary<string, string>(); if (verbose == true) { Console.WriteLine("Finding files..."); } foreach (var relPath in inputPaths) { string inputPath = Path.GetFullPath(relPath); if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true) { inputPath = inputPath.Substring(0, inputPath.Length - 1); } foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories)) { bool hasName; string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant(); if (paths.ContainsKey(partPath) == true) { Console.WriteLine("Ignoring {0} duplicate.", partPath); continue; } paths[partPath] = fullPath; } } using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { var pkg = new PackageFile(); output.Seek(PackageFile.HeaderSize, SeekOrigin.Begin); if (verbose == true) { Console.WriteLine("Writing files to package..."); } foreach (var kvp in paths) { if (verbose == true) { Console.WriteLine(kvp.Key); } using (var input = File.OpenRead(kvp.Value)) { var entry = new Package.Entry(); entry.Name = kvp.Key; entry.TimeStamp = File.GetLastWriteTime(kvp.Value); entry.UncompressedSize = input.Length; entry.Offset = output.Position; int blockCount = (int)((entry.UncompressedSize + 0xFFFF) >> 16); // .Align(0x10000) / 0x10000; var compressedBlocks = new byte[blockCount][]; var compressedSizes = new int[blockCount]; var uncompressedBlock = new byte[0x10000]; long left = input.Length; for (int i = 0; i < blockCount; i++) { int uncompressedSize = input.Read( uncompressedBlock, 0, uncompressedBlock.Length); var lzf = new LZF(); compressedBlocks[i] = new byte[0x20000]; int compressedSize = lzf.Compress( uncompressedBlock, uncompressedSize, compressedBlocks[i], compressedBlocks[i].Length); if (compressedSize == 0) { throw new InvalidOperationException(); } compressedSizes[i] = compressedSize; } int offset = blockCount * 4; for (int i = 0; i < blockCount; i++) { output.WriteValueS32(offset); offset += compressedSizes[i]; } for (int i = 0; i < blockCount; i++) { output.Write(compressedBlocks[i], 0, compressedSizes[i]); } entry.CompressedSize = offset; pkg.Entries.Add(entry); } } if (verbose == true) { Console.WriteLine("Writing package header..."); } pkg.Serialize(output, output.Length); } }