mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-21 09:11:20 +00:00
152 lines
3.9 KiB
C#
Executable file
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;
|
|
}
|
|
}
|
|
}
|