/// <summary> /// Assume header is clean /// </summary> /// <param name="br"></param> /// <param name="bw"></param> /// <param name="context"></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.OffsetUnknown1 = br.ReadUInt32(); header.OffsetUnknown2 = br.ReadUInt32(); header.OffsetResourceOffsets = 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.OffsetUnknown1) .Concat(BitConverter.GetBytes(header.OffsetUnknown2)) .Concat(BitConverter.GetBytes(header.OffsetResourceOffsets)).ToArray(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; context.Write(header.Checksum, bw); context.Write(header.OffsetUnknown1, bw); context.Write(header.OffsetUnknown2, bw); context.Write(header.OffsetResourceOffsets, bw); } } }
/// <summary> /// Assume header is encrypted /// </summary> /// <param name="br"></param> /// <param name="bw"></param> /// <param name="context"></param> /// <param name="header"></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.OffsetUnknownOffsets = context.ReadUInt32(br); header.OffsetUnknownLengths = context.ReadUInt32(br); header.OffsetUnknownData = 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.OffsetUnknownOffsets) .Concat(BitConverter.GetBytes(header.OffsetUnknownLengths)) .Concat(BitConverter.GetBytes(header.OffsetUnknownData)).ToArray(); adler32.Update(checkBuffer); header.Checksum = (uint)adler32.Checksum; bw.Write(header.Checksum); bw.Write(header.OffsetUnknownOffsets); bw.Write(header.OffsetUnknownLengths); bw.Write(header.OffsetUnknownData); } } }