using System.IO;
using FSO.Files.Utils;
namespace FSO.Files.Formats.IFF.Chunks
{
///
/// This chunk type holds Behavior code in SimAntics.
///
public class BHAV : IffChunk
{
public TREE RuntimeTree;
public BHAVInstruction[] Instructions = new BHAVInstruction[0];
public byte Type;
public byte Args;
public ushort Locals;
public ushort Flags;
public uint RuntimeVer;
///
/// Reads a BHAV from a stream.
///
/// Iff instance.
/// A Stream instance holding a BHAV chunk.
public override void Read(IffFile iff, System.IO.Stream stream)
{
using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
{
var version = io.ReadUInt16();
uint count = 0;
if (version == 0x8000)
{
count = io.ReadUInt16();
io.Skip(8);
}
else if (version == 0x8001)
{
count = io.ReadUInt16();
var unknown = io.ReadBytes(8);
}
else if (version == 0x8002)
{
count = io.ReadUInt16();
this.Type = io.ReadByte();
this.Args = io.ReadByte();
this.Locals = io.ReadUInt16();
this.Flags = io.ReadUInt16();
io.Skip(2);
}
else if (version == 0x8003)
{
this.Type = io.ReadByte();
this.Args = io.ReadByte();
this.Locals = io.ReadByte();
io.Skip(2);
this.Flags = io.ReadUInt16();
count = io.ReadUInt32();
}
Instructions = new BHAVInstruction[count];
for (var i = 0; i < count; i++)
{
var instruction = new BHAVInstruction();
instruction.Opcode = io.ReadUInt16();
instruction.TruePointer = io.ReadByte();
instruction.FalsePointer = io.ReadByte();
instruction.Operand = io.ReadBytes(8);
Instructions[i] = instruction;
}
}
}
public override bool Write(IffFile iff, Stream stream)
{
using (var io = IoWriter.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
{
if (IffFile.TargetTS1)
{ //version 0x8002
io.WriteUInt16(0x8002);
io.WriteUInt16((ushort)Instructions.Length);
io.WriteByte(Type);
io.WriteByte(Args);
io.WriteUInt16(Locals);
io.WriteUInt16(Flags);
io.WriteBytes(new byte[] { 0, 0 });
foreach (var inst in Instructions)
{
io.WriteUInt16(inst.Opcode);
io.WriteByte(inst.TruePointer);
io.WriteByte(inst.FalsePointer);
io.WriteBytes(inst.Operand);
}
}
else
{
io.WriteUInt16(0x8003);
io.WriteByte(Type);
io.WriteByte(Args);
io.WriteByte((byte)Locals);
io.WriteBytes(new byte[] { 0, 0 });
io.WriteUInt16(Flags);
io.WriteUInt32((ushort)Instructions.Length);
foreach (var inst in Instructions)
{
io.WriteUInt16(inst.Opcode);
io.WriteByte(inst.TruePointer);
io.WriteByte(inst.FalsePointer);
io.WriteBytes(inst.Operand);
}
}
}
return true;
}
}
public class BHAVInstruction
{
public ushort Opcode;
public byte TruePointer;
public byte FalsePointer;
public byte[] Operand;
public bool Breakpoint; //only used at runtime
}
}