mysimulation/server/tso.files/Formats/IFF/Chunks/IffFieldEncode.cs
Tony Bark 8fec258215 Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
2024-05-01 04:38:12 -04:00

152 lines
3.9 KiB
C#
Executable file

using FSO.Files.Utils;
using System;
using System.IO;
namespace FSO.Files.Formats.IFF.Chunks
{
/// <summary>
/// Used to read values from field encoded stream.
/// </summary>
public class IffFieldEncode : IOProxy
{
private byte bitPos = 0;
private byte curByte = 0;
private bool odd = false;
public byte[] widths = { 5, 8, 13, 16 };
public byte[] widths2 = { 6, 11, 21, 32 };
public bool StreamEnd;
public void setBytePos(int n)
{
io.Seek(SeekOrigin.Begin, n);
curByte = io.ReadByte();
bitPos = 0;
}
public override ushort ReadUInt16()
{
return (ushort)ReadField(false);
}
public override short ReadInt16()
{
return (short)ReadField(false);
}
public override int ReadInt32()
{
return (int)ReadField(true);
}
public override uint ReadUInt32()
{
return (uint)ReadField(true);
}
public override float ReadFloat()
{
return (float)ReadField(true);
//this is incredibly wrong
}
private long ReadField(bool big)
{
if (ReadBit() == 0) return 0;
uint code = ReadBits(2);
byte width = (big) ? widths2[code] : widths[code];
long value = ReadBits(width);
value |= -(value & (1 << (width - 1)));
return value;
}
public Tuple<long, int> DebugReadField(bool big)
{
if (ReadBit() == 0) return new Tuple<long, int>(0, 0);
uint code = ReadBits(2);
byte width = (big) ? widths2[code] : widths[code];
long value = ReadBits(width);
value |= -(value & (1 << (width - 1)));
return new Tuple<long, int>(value, width);
}
public Tuple<byte, byte, bool, long> MarkStream()
{
return new Tuple<byte, byte, bool, long>(bitPos, curByte, odd, io.Position);
}
public void RevertToMark(Tuple<byte, byte, bool, long> mark)
{
StreamEnd = false;
bitPos = mark.Item1;
curByte = mark.Item2;
odd = mark.Item3;
io.Seek(SeekOrigin.Begin, mark.Item4);
}
public uint ReadBits(int n)
{
uint total = 0;
for (int i = 0; i < n; i++)
{
total += (uint)(ReadBit() << ((n - i) - 1));
}
return total;
}
private byte ReadBit()
{
byte result = (byte)((curByte & (1 << (7 - bitPos))) >> (7 - bitPos));
if (++bitPos > 7)
{
bitPos = 0;
try
{
curByte = io.ReadByte();
odd = !odd;
}
catch (Exception)
{
curByte = 0; //no more data, read 0
odd = !odd;
StreamEnd = true;
}
}
return result;
}
public string ReadString(bool nextField)
{
if (bitPos == 0)
{
io.Seek(SeekOrigin.Current, -1);
odd = !odd;
}
var str = io.ReadNullTerminatedString();
if ((str.Length % 2 == 0) == !odd) io.ReadByte(); //2 byte pad
bitPos = 8;
if (nextField && io.HasMore)
{
curByte = io.ReadByte();
odd = true;
bitPos = 0;
} else
{
odd = false;
}
return str;
}
public IffFieldEncode(IoBuffer io) : base(io)
{
curByte = io.ReadByte();
odd = !odd;
bitPos = 0;
}
}
}