private static void WriteHeader(this BinaryWriter bw, DrpArchive archive, uint seed) { bw.Write(DrpArchive.ArchiveHeaderMagic); bw.Write(seed); if (archive.Encrypted) { var rng = XorShiftUtil.GetEncryptionRng(seed, archive.SeedTable); bw.Write(rng.GetNext(uint.MaxValue) ^ DrpArchive.CryptoBlockMagic); bw.Write(rng.GetNext(uint.MaxValue) ^ 0x90u); bw.Write(rng.GetNext(uint.MaxValue) ^ (uint)archive.FileCount); } else { bw.Write(DrpArchive.CryptoBlockMagic); bw.Write(0x90u); bw.Write(archive.FileCount); } bw.Write(archive.SeedTable); }
private static void WriteFooter(this BinaryWriter bw, DrpArchive archive, uint seed) { var asUint = MemoryMarshal.Cast <byte, uint>(archive.Footer); if (archive.Encrypted) { var rng = XorShiftUtil.GetEncryptionRng(seed, archive.SeedTable); foreach (var u32 in asUint) { bw.Write(u32 ^ rng.GetNext(uint.MaxValue)); } } else { foreach (var u32 in asUint) { bw.Write(u32); } } }
private static void WriteEntry(this BinaryWriter bw, DrpFileEntry entry, bool encrypted, ReadOnlySpan <byte> table) { Debug.WriteLine($"Writing entry at 0x0{bw.BaseStream.Position:X}."); var h = entry.Header; var seed = entry.GetChecksum(); ReadOnlySpan <byte> payload = entry.GetData(); h.CompressedSize = h.DecompressedSize = payload.Length; if (entry.Compressed) { payload = Oodle.Compress(payload, out int size); h.CompressedSize = 4 + size; Debug.Assert((payload.Length & 3) == 0); } var nameSize = (entry.FileName.Length | 3) + 1; // next multiple of 4 var dataSize = (h.CompressedSize + 3) & ~3; // roundup multiple of 4 h.SizeTotal = 0x18 + nameSize + dataSize; bw.Write(seed); if (encrypted) { var rng = XorShiftUtil.GetEncryptionRng(seed, table); bw.Write(rng.GetNext(uint.MaxValue) ^ h.Magic); bw.Write(rng.GetNext(uint.MaxValue) ^ (uint)h.SizeTotal); bw.Write(rng.GetNext(uint.MaxValue) ^ h.Extension); bw.Write(rng.GetNext(uint.MaxValue) ^ (uint)h.CompressedSize); bw.Write(rng.GetNext(uint.MaxValue) ^ (uint)h.DecompressedSize); Span <byte> temp = stackalloc byte[4]; var fn = entry.FileName; int ctr = 0; foreach (var c in fn) { temp[ctr++] = (byte)c; if (ctr != 4) { continue; } bw.Write(rng.GetNext(uint.MaxValue) ^ BitConverter.ToUInt32(temp)); temp.Clear(); ctr = 0; } if (ctr == 0) { bw.Write(rng.GetNext(uint.MaxValue) ^ 0u); } else { bw.Write(rng.GetNext(uint.MaxValue) ^ BitConverter.ToUInt32(temp)); } var asUint = MemoryMarshal.Cast <byte, uint>(payload); if (entry.Compressed) { bw.Write(rng.GetNext(uint.MaxValue) ^ DrpFileHeader.CompressedDataMagic); } foreach (var u32 in asUint) { bw.Write(rng.GetNext(uint.MaxValue) ^ u32); } var slice = payload[(asUint.Length * 4)..];