public static void WriteFrame(SPR2Frame frame, IoWriter output)
{
var bytes = frame.PalData;
var col = frame.PixelData;
var zs = frame.ZBufferData;
int index = 0;
int blankLines = 0;
for (int y=0; y<frame.Height; y++)
{
byte lastCmd = 0;
List<byte> dataBuf = new List<byte>();
int rlecount = 0;
bool anySolid = false;
var scanStream = new MemoryStream();
var scanOut = IoWriter.FromStream(scanStream, ByteOrder.LITTLE_ENDIAN);
for (int x=0; x<frame.Width; x++)
{
byte plt = bytes[index];
byte a = col[index].A;
byte z = zs[index];
var cmd = getCmd(plt, a, z);
if (x == 0 || cmd != lastCmd)
{
if (x != 0)
{
//write a command to write the last sequence of pixels
scanOut.WriteUInt16((ushort)(((int)lastCmd<<13)|rlecount));
if ((dataBuf.Count % 2) != 0) dataBuf.Add(0);
scanOut.WriteBytes(dataBuf.ToArray());
dataBuf.Clear();
}
lastCmd = cmd;
rlecount = 0;
}
switch (cmd)
{
case 0x1:
case 0x2:
dataBuf.Add(z);
dataBuf.Add(plt);
if (cmd == 0x2) dataBuf.Add((byte)Math.Ceiling(a/ 8.2258064516129032258064516129032));
anySolid = true;
break;
case 0x6:
dataBuf.Add(plt);
anySolid = true;
break;
default:
break;
}
rlecount++;
index++;
}
if (anySolid)
{
//write a command to write the last sequence of pixels
scanOut.WriteUInt16((ushort)(((int)lastCmd << 13) | rlecount));
if ((dataBuf.Count % 2) != 0) dataBuf.Add(0);
scanOut.WriteBytes(dataBuf.ToArray());
dataBuf.Clear();
}
var scanData = scanStream.ToArray();
if (scanData.Length == 0)
blankLines++; //line is transparent
else
{
if (blankLines > 0)
{
//add transparent lines before our new command
output.WriteUInt16((ushort)((0x4<<13) | blankLines));
blankLines = 0;
}
output.WriteUInt16((ushort)(scanData.Length+2));
output.WriteBytes(scanData);
}
}
if (blankLines > 0)
{
//add transparent lines before our new command
output.WriteUInt16((ushort)((0x4 << 13) | blankLines));
blankLines = 0;
}
output.WriteUInt16((ushort)(0x5<<13));
return;
}