mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-20 08:41:21 +00:00
142 lines
4.8 KiB
C#
Executable file
142 lines
4.8 KiB
C#
Executable file
using FSO.Files.Utils;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace FSO.Files.Formats.IFF.Chunks
|
|
{
|
|
public class ARRY : IffChunk
|
|
{
|
|
public int Width;
|
|
public int Height;
|
|
public ARRYType Type;
|
|
public byte[] Data;
|
|
public byte[] TransposeData
|
|
{
|
|
get
|
|
{
|
|
var stride = (int)Type;
|
|
byte[] result = new byte[Data.Length];
|
|
for (int i = 0; i < Data.Length; i += stride)
|
|
{
|
|
var divI = i / stride;
|
|
var x = divI % Width;
|
|
var y = divI / Width;
|
|
int targetIndex = y * stride + x * stride * Width;
|
|
for (int j = 0; j < stride; j++)
|
|
{
|
|
result[targetIndex++] = Data[i + j];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public override void Read(IffFile iff, Stream stream)
|
|
{
|
|
using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
|
|
{
|
|
var zero = io.ReadInt32();
|
|
Width = io.ReadInt32();
|
|
Height = io.ReadInt32();
|
|
Type = (ARRYType)io.ReadInt32();
|
|
var dataByteSize = ByteSize();
|
|
Data = new byte[Width * Height * dataByteSize];
|
|
var unknown = io.ReadInt32();
|
|
|
|
|
|
int currentPosition = 0;
|
|
while (io.HasMore)
|
|
{
|
|
switch (Type)
|
|
{
|
|
default:
|
|
//bit format:
|
|
//1000 yyyy yyxx xxxx
|
|
|
|
var flre = io.ReadUInt16();
|
|
if (flre == 0) break;
|
|
bool rawFill = (flre & 0x8000) == 0;
|
|
if (rawFill)
|
|
{
|
|
for (int i=0; i<flre; i++)
|
|
{
|
|
if (!io.HasMore) return;
|
|
Data[currentPosition++] = io.ReadByte();
|
|
if (currentPosition > Data.Length) return;
|
|
}
|
|
if ((flre & 1) == 1) io.ReadByte();
|
|
continue;
|
|
}
|
|
|
|
var lastPosition = currentPosition;
|
|
currentPosition += flre & 0x7FFF;
|
|
currentPosition %= Data.Length; //wrap to data size
|
|
if (currentPosition == 0) return;
|
|
|
|
var pad = io.ReadByte();//ReadElement(io); //pad the previous entries with this data
|
|
//if ((dataByteSize & 1) == 1)
|
|
io.ReadByte(); //padded to 16 bits
|
|
|
|
while (lastPosition < currentPosition)
|
|
{
|
|
Data[lastPosition++] = pad;
|
|
}
|
|
|
|
if (!io.HasMore) return;
|
|
|
|
var size = io.ReadInt16();
|
|
if ((size & 0x8000) != 0)
|
|
{
|
|
io.Seek(SeekOrigin.Current, -2);
|
|
continue;
|
|
}
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
Data[currentPosition++] = io.ReadByte();//ReadElement(io);
|
|
currentPosition %= Data.Length;
|
|
}
|
|
|
|
if ((size & 1) == 1) io.ReadByte(); //16-bit pad
|
|
|
|
currentPosition %= Data.Length; //12 bit wrap
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public int ByteSize()
|
|
{
|
|
return (int)Type;
|
|
}
|
|
|
|
|
|
public string DebugPrint()
|
|
{
|
|
var dataByteSize = ByteSize();
|
|
var result = new StringBuilder();
|
|
int index = 0;
|
|
for (int y = 0; y < Height; y++)
|
|
{
|
|
for (int x = 0; x < Width; x++)
|
|
{
|
|
var item = Data[index];
|
|
var str = item.ToString().PadLeft(3, ' ');
|
|
result.Append((str == " 0") ? " ." : str);
|
|
index += dataByteSize;
|
|
}
|
|
result.AppendLine();
|
|
}
|
|
return result.ToString();
|
|
}
|
|
}
|
|
|
|
public enum ARRYType : int
|
|
{
|
|
RLEAlt = 4, //altitude
|
|
RLEFloor = 1, //floors, "ground", grass, flags, pool "ARRY(9)", water
|
|
RLEWalls = 8, //walls
|
|
Objects = 2, //objects "ARRY(3)"
|
|
}
|
|
}
|