/// <summary> /// Decodes buffer. /// </summary> /// <param name="buffer"></param> /// <param name="seed"></param> private void Decode(ref byte[] buffer) { var mt = new MTRandom((uint)((this.Seed << 7) ^ 0xA9C36DE1)); for (int i = 0; i < buffer.Length; ++i) { buffer[i] = (byte)(buffer[i] ^ mt.GetUInt32()); } }
/// <summary> /// Decodes buffer. /// </summary> /// <param name="buffer"></param> /// <param name="seed"></param> private void Decode(ref byte[] buffer) { // KR beta (v1) didn't have encoding yet if (this.Header.FormatVersion == 1) { return; } var mt = new MTRandom((this.Seed << 7) ^ 0xA9C36DE1); for (var i = 0; i < buffer.Length; ++i) { buffer[i] = (byte)(buffer[i] ^ mt.GetUInt32()); } }
/// <summary> /// Writes pack file to given location. /// </summary> /// <param name="filePath"></param> public void Save(string filePath, CompressionStrength compression = CompressionStrength.Default) { var blankLength = this.Header.BlankLength; var fileCount = this.Count; using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None)) using (var bw = new BinaryWriter(fs)) { var entryStarts = new Dictionary <IPackListEntry, long>(); // Header bw.Write(this.Header.Signature); bw.Write(this.Header.FormatVersion); bw.Write(this.Header.PackVersion); bw.Write(fileCount); bw.Write(this.Header.FileTime1.ToFileTimeUtc()); bw.Write(this.Header.FileTime2.ToFileTimeUtc()); bw.Write(Encoding.UTF8.GetBytes(this.Header.BasePath.PadRight(480, '\0'))); bw.Write(fileCount); var headerLengthsStart = bw.BaseStream.Position; bw.Write(this.Header.ListLength); bw.Write(blankLength); bw.Write(this.Header.DataLength); bw.Write(this.Header.Zero); // List var entryListStart = bw.BaseStream.Position; foreach (var entry in _entries.Values) { bw.Write((byte)entry.NameType); if (entry.NameType <= PackListNameType.L64) { var size = (0x10 * ((byte)entry.NameType + 1)); var bytes = Encoding.UTF8.GetBytes(entry.RelativePath.PadRight(size - 1, '\0')); bw.Write(bytes); } else if (entry.NameType == PackListNameType.L96) { var size = 0x60; var bytes = Encoding.UTF8.GetBytes(entry.RelativePath.PadRight(size - 1, '\0')); bw.Write(bytes); } else if (entry.NameType == PackListNameType.LDyn) { var bytes = Encoding.UTF8.GetBytes(entry.RelativePath + '\0'); bw.Write(bytes.Length); bw.Write(bytes); } else { throw new Exception("Unknown entry name type '" + entry.NameType + "'."); } bw.Write(entry.Seed); bw.Write(entry.Zero); entryStarts[entry] = bw.BaseStream.Position; bw.Write(0); // DataOffset bw.Write(0); // CompressedSize bw.Write(0); // DecompressedSize bw.Write(entry.IsCompressed ? 1 : 0); bw.Write(entry.FileTime1.ToFileTimeUtc()); bw.Write(entry.FileTime2.ToFileTimeUtc()); bw.Write(entry.FileTime3.ToFileTimeUtc()); bw.Write(entry.FileTime4.ToFileTimeUtc()); bw.Write(entry.FileTime5.ToFileTimeUtc()); } var entryListEnd = bw.BaseStream.Position; var entryListLength = (int)(entryListEnd - entryListStart); bw.Write(new byte[blankLength]); // Data var dataOffset = 0; var dataListStart = bw.BaseStream.Position; foreach (var entry in _entries.Values) { // Get data var data = entry.GetData(); var uncompressedSize = data.Length; if (entry.IsCompressed) { // Compress data var dataStart = bw.BaseStream.Position; byte[] compressed; using (var ms = new MemoryStream()) { var zlib = new ZOutputStream(ms, (int)compression); zlib.Write(data, 0, data.Length); zlib.finish(); compressed = ms.ToArray(); } var mt = new MTRandom((entry.Seed << 7) ^ 0xA9C36DE1); for (var i = 0; i < compressed.Length; ++i) { compressed[i] = (byte)(compressed[i] ^ mt.GetUInt32()); } data = compressed; } bw.Write(data); var dataEnd = bw.BaseStream.Position; var compressedSize = data.Length; var listPos = entryStarts[entry]; // Overwrite entry information bw.BaseStream.Seek(listPos, SeekOrigin.Begin); bw.Write(dataOffset); bw.Write(compressedSize); bw.Write(uncompressedSize); bw.BaseStream.Seek(dataEnd, SeekOrigin.Begin); dataOffset += compressedSize; } var dataListEnd = bw.BaseStream.Position; var dataListLength = (int)(dataListEnd - dataListStart); bw.BaseStream.Seek(headerLengthsStart, SeekOrigin.Begin); bw.Write(entryListLength + blankLength); bw.Seek(4, SeekOrigin.Current); bw.Write(dataListLength); bw.BaseStream.Seek(dataListEnd, SeekOrigin.Begin); } }