/// <summary> /// Update Checksum /// </summary> /// <returns>Current Checksum</returns> public uint UpdateChecksum() { var checkBuffer = BitConverter.GetBytes(HeaderLength) .Concat(BitConverter.GetBytes(OffsetNames)) .Concat(BitConverter.GetBytes(OffsetStrings)) .Concat(BitConverter.GetBytes(OffsetStringsData)) .Concat(BitConverter.GetBytes(OffsetChunkOffsets)) .Concat(BitConverter.GetBytes(OffsetChunkLengths)) .Concat(BitConverter.GetBytes(OffsetChunkData)) .Concat(BitConverter.GetBytes(OffsetEntries)) .ToArray(); Adler32 adler32 = new Adler32(); adler32.Update(checkBuffer); if (Version < 4) { Checksum = (uint)adler32.Checksum; return(Checksum); } checkBuffer = BitConverter.GetBytes(OffsetExtraChunkOffsets) .Concat(BitConverter.GetBytes(OffsetExtraChunkLengths)) .Concat(BitConverter.GetBytes(OffsetExtraChunkData)) .ToArray(); adler32.Update(checkBuffer); Checksum = (uint)adler32.Checksum; return(Checksum); }
/// <summary> /// Assume header is encrypted /// </summary> /// <param name="br"></param> /// <param name="bw"></param> /// <param name="context"></param> private static void WriteDecryptPartialHeader(BinaryReader br, BinaryWriter bw, PsbStreamContext context, PsbHeader header) { header.HeaderLength = context.ReadUInt32(br); header.OffsetNames = context.ReadUInt32(br); header.OffsetStrings = context.ReadUInt32(br); header.OffsetStringsData = context.ReadUInt32(br); header.OffsetChunkOffsets = context.ReadUInt32(br); header.OffsetChunkLengths = context.ReadUInt32(br); header.OffsetChunkData = context.ReadUInt32(br); header.OffsetEntries = context.ReadUInt32(br); if (header.Version > 2) { header.Checksum = context.ReadUInt32(br); } if (header.Version > 3) { header.OffsetUnknown1 = context.ReadUInt32(br); header.OffsetUnknown2 = context.ReadUInt32(br); header.OffsetResourceOffsets = context.ReadUInt32(br); } //var checksumStartPosition = bw.BaseStream.Position; bw.Write(header.HeaderLength); bw.Write(header.OffsetNames); bw.Write(header.OffsetStrings); bw.Write(header.OffsetStringsData); bw.Write(header.OffsetChunkOffsets); bw.Write(header.OffsetChunkLengths); bw.Write(header.OffsetChunkData); bw.Write(header.OffsetEntries); //var checksumPosition = bw.BaseStream.Position; if (header.Version > 2) { int checkLength = 32; bw.BaseStream.Seek(-checkLength, SeekOrigin.Current); var checkBuffer = new byte[checkLength]; bw.BaseStream.Read(checkBuffer, 0, checkLength); Adler32 adler32 = new Adler32(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; if (header.Version == 3) { bw.Write(header.Checksum); } else //PSBv4 { checkBuffer = BitConverter.GetBytes(header.OffsetUnknown1) .Concat(BitConverter.GetBytes(header.OffsetUnknown2)) .Concat(BitConverter.GetBytes(header.OffsetResourceOffsets)).ToArray(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; bw.Write(header.Checksum); bw.Write(header.OffsetUnknown1); bw.Write(header.OffsetUnknown2); bw.Write(header.OffsetResourceOffsets); } } }
public static void CompressToMdfFile(this PsbFile psbFile, string outputPath = null, bool fast = true) { var bytes = File.ReadAllBytes(psbFile.Path); Adler32 checksumer = new Adler32(); checksumer.Update(bytes); var checksum = (uint)checksumer.Checksum; checksumer = null; MemoryStream ms = new MemoryStream(bytes); using (FileStream fs = new FileStream(outputPath ?? psbFile.Path + ".mdf", FileMode.Create)) { BinaryWriter bw = new BinaryWriter(fs); bw.WriteStringZeroTrim(Signature); bw.Write((uint)ms.Length); bw.Write(ZlibCompress.Compress(ms, fast)); bw.WriteBE(checksum); ms.Dispose(); bw.Flush(); } }
public static Stream CompressPsbToMdfStream(Stream input, bool fast = true) { var pos = input.Position; Adler32 checksumer = new Adler32(); checksumer.Update(input); var checksum = (uint)checksumer.Checksum; checksumer = null; input.Position = pos; MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8, true); bw.WriteStringZeroTrim(Signature); bw.Write((uint)input.Length); bw.Write(ZlibCompress.Compress(input, fast)); bw.WriteBE(checksum); bw.Flush(); bw.Dispose(); ms.Seek(0, SeekOrigin.Begin); return(ms); }
/// <summary> /// Assume header is clean /// </summary> /// <param name="br"></param> /// <param name="bw"></param> /// <param name="context"></param> /// <param name="header"></param> private static void WriteEncryptPartialHeader(BinaryReader br, BinaryWriter bw, PsbStreamContext context, PsbHeader header) { var checksumStartPosition = br.BaseStream.Position; header.HeaderLength = br.ReadUInt32(); header.OffsetNames = br.ReadUInt32(); if (header.HeaderLength == 0) { header.HeaderLength = header.OffsetNames; } header.OffsetStrings = br.ReadUInt32(); header.OffsetStringsData = br.ReadUInt32(); header.OffsetChunkOffsets = br.ReadUInt32(); header.OffsetChunkLengths = br.ReadUInt32(); header.OffsetChunkData = br.ReadUInt32(); header.OffsetEntries = br.ReadUInt32(); if (header.Version > 2) { header.Checksum = br.ReadUInt32(); } if (header.Version > 3) { header.OffsetUnknownOffsets = br.ReadUInt32(); header.OffsetUnknownLengths = br.ReadUInt32(); header.OffsetUnknownData = br.ReadUInt32(); } var checksumEndPosition = br.BaseStream.Position; context.Write(header.HeaderLength, bw); context.Write(header.OffsetNames, bw); context.Write(header.OffsetStrings, bw); context.Write(header.OffsetStringsData, bw); context.Write(header.OffsetChunkOffsets, bw); context.Write(header.OffsetChunkLengths, bw); context.Write(header.OffsetChunkData, bw); context.Write(header.OffsetEntries, bw); if (header.Version > 2) { int checkLength = 32; br.BaseStream.Seek(checksumStartPosition, SeekOrigin.Begin); var checkBuffer = new byte[checkLength]; br.BaseStream.Read(checkBuffer, 0, checkLength); br.BaseStream.Seek(checksumEndPosition, SeekOrigin.Begin); //Jump back Adler32 adler32 = new Adler32(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; if (header.Version == 3) { context.Write(header.Checksum, bw); } else //PSBv4 { checkBuffer = BitConverter.GetBytes(header.OffsetUnknownOffsets) .Concat(BitConverter.GetBytes(header.OffsetUnknownLengths)) .Concat(BitConverter.GetBytes(header.OffsetUnknownData)).ToArray(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; context.Write(header.Checksum, bw); context.Write(header.OffsetUnknownOffsets, bw); context.Write(header.OffsetUnknownLengths, bw); context.Write(header.OffsetUnknownData, bw); } } }