Files
korenkonder_PD_Tool/KKdBaseLib/F2/POF.cs
T
2020-05-17 14:57:58 +03:00

106 lines
3.9 KiB
C#

namespace KKdBaseLib.F2
{
public struct POF : INull
{
public KKdList<long> Offsets;
public bool IsNull => Offsets. IsNull;
public bool NotNull => Offsets.NotNull;
public int Length => length(false).A(0x10);
public int LengthX => length( true).A(0x10);
public unsafe void Read(byte[] data, bool shiftX)
{
Value Val = 0;
Offsets = KKdList<long>.New;
fixed (byte* ptr = data)
{
int i = 0, offset = 0, v = 0;
byte bitShift = (byte)(shiftX ? 3 : 2);
int length = *(int*)ptr - 4;
byte* localPtr = ptr + 4;
while (length > i)
{
v = *ptr & 0x3F;
Val = (Value)(*ptr & 0xC0);
localPtr++; i++;
if (Val == Value.Int32 )
{ v = (v << 24) | (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; localPtr += 3; i += 3; }
else if (Val == Value.Int16 )
{ v = (v << 8) | ptr[0]; localPtr += 1; i += 3; }
else if (Val == Value.Invalid) break;
offset += v;
Offsets.Add(offset << bitShift);
}
}
}
public unsafe byte[] Write(bool shiftX)
{
Offsets.Sort();
long offset = 0;
byte bitShift = (byte)(shiftX ? 3 : 2);
int max1 = 0x00100 >> bitShift;
int max2 = 0x10000 >> bitShift;
byte[] data = new byte[length(shiftX)];
fixed (byte* ptr = data)
{
byte Val = 0;
*(int*)ptr = length(shiftX);
byte* localPtr = ptr + 4;
for (int i = 0; i < Offsets.Count; i++)
{
offset = Offsets[i];
if (i > 0) { offset -= Offsets[i - 1]; if (offset == 0) continue; }
offset >>= bitShift;
Val = (byte)(offset > max2 ? Value.Int32 : offset > max1 ? Value.Int16 : Value.Int8);
if (offset < max1) *localPtr = (byte)(Val | offset );
else if (offset < max2) { *localPtr = (byte)(Val | (offset >> 8)); localPtr++;
*localPtr = (byte) offset ; }
else { *localPtr = (byte)(Val | (offset >> 24)); localPtr++;
*localPtr = (byte) (offset >> 16) ; localPtr++;
*localPtr = (byte) (offset >> 8) ; localPtr++;
*localPtr = (byte) offset ; }
localPtr++;
}
}
return data;
}
private int length(bool shiftX = false)
{
int length = 5;
long offset = 0;
byte bitShift = (byte)(shiftX ? 3 : 2);
int max1 = 0x00100 >> bitShift;
int max2 = 0x10000 >> bitShift;
for (int i = 0; i < Offsets.Count; i++)
{
offset = Offsets[i];
if (i > 0) { offset -= Offsets[i - 1]; if (offset == 0) continue; }
offset >>= bitShift;
if (offset < max1) length += 1;
else if (offset < max2) length += 2;
else length += 4;
}
return length;
}
public enum Value : byte
{
Invalid = 0b00000000,
Int8 = 0b01000000,
Int16 = 0b10000000,
Int32 = 0b11000000,
}
public override string ToString() =>
$"{(NotNull ? $"Offsets Count: {Offsets.Count}" : "No POF")}";
}
}