93 lines
2.9 KiB
C#
93 lines
2.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace AnotherReplayReader.ReplayFile
|
|
{
|
|
internal enum ReplayFooterOption
|
|
{
|
|
SeekToFooter,
|
|
CurrentlyAtFooter,
|
|
}
|
|
|
|
internal sealed class ReplayFooter
|
|
{
|
|
public const uint Terminator = 0x7FFFFFFF;
|
|
public static readonly byte[] FooterString = Encoding.ASCII.GetBytes("RA3 REPLAY FOOTER");
|
|
|
|
private readonly byte[] _data;
|
|
|
|
public uint FinalTimeCode { get; }
|
|
public TimeSpan ReplayLength => TimeSpan.FromSeconds(FinalTimeCode / Replay.FrameRate);
|
|
|
|
public ReplayFooter(BinaryReader reader, ReplayFooterOption option)
|
|
{
|
|
var currentPosition = reader.BaseStream.Position;
|
|
reader.BaseStream.Seek(-4, SeekOrigin.End);
|
|
var footerLength = reader.ReadInt32();
|
|
|
|
if (option == ReplayFooterOption.SeekToFooter)
|
|
{
|
|
currentPosition = reader.BaseStream.Length - footerLength;
|
|
}
|
|
|
|
reader.BaseStream.Seek(currentPosition, SeekOrigin.Begin);
|
|
var footer = reader.ReadBytes(footerLength);
|
|
|
|
if (footer.Length != footerLength || reader.BaseStream.Position != reader.BaseStream.Length)
|
|
{
|
|
throw new InvalidDataException("Invalid footer");
|
|
}
|
|
|
|
using var footerStream = new MemoryStream(footer);
|
|
using var footerReader = new BinaryReader(footerStream);
|
|
var footerString = footerReader.ReadBytes(17);
|
|
if (!footerString.SequenceEqual(FooterString))
|
|
{
|
|
throw new InvalidDataException("Invalid footer, no footer string");
|
|
}
|
|
FinalTimeCode = footerReader.ReadUInt32();
|
|
_data = footerReader.ReadBytes(footer.Length - 25);
|
|
if (footerReader.ReadInt32() != footerLength)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
}
|
|
|
|
public ReplayFooter(uint finalTimeCode)
|
|
{
|
|
FinalTimeCode = finalTimeCode;
|
|
_data = new byte[] { 0x02, 0x1A, 0x00, 0x00, 0x00 };
|
|
}
|
|
|
|
public float[]? TryGetKillDeathRatios()
|
|
{
|
|
if (_data.Length < 24)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var ratios = new float[6];
|
|
using var stream = new MemoryStream(_data, _data.Length - 24, 24);
|
|
using var reader = new BinaryReader(stream);
|
|
for (var i = 0; i < ratios.Length; ++i)
|
|
{
|
|
ratios[i] = reader.ReadSingle();
|
|
}
|
|
return ratios;
|
|
}
|
|
|
|
public void WriteTo(BinaryWriter writer)
|
|
{
|
|
writer.Write(Terminator);
|
|
writer.Write(FooterString);
|
|
writer.Write(FinalTimeCode);
|
|
writer.Write(_data);
|
|
writer.Write(FooterString.Length + _data.Length + 8);
|
|
}
|
|
}
|
|
|
|
|
|
}
|