public PaletteMap(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //Reader.BaseStream.Position = INDEX_PALTID; /*m_ID = (uint)numPalettes++; m_ID = Reader.ReadUInt32();*/ //m_Colors = new int[256]; m_Colors = new Color[256]; Reader.BaseStream.Position = 16; /*if (Reader.BaseStream.ReadByte() == 0) Reader.BaseStream.Position = 80; else Reader.BaseStream.Position = 16;*/ for (int i = 0; i < 256; i++) { //Reader.BaseStream.Position += 3; byte[] colors = new byte[] {}; if ((Reader.BaseStream.Length - Reader.BaseStream.Position) >= 3) m_Colors[i] = Color.FromArgb(Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte()); else m_Colors[i] = Color.FromArgb(255, 0x80, 0x80, 0x80); } Reader.Close(); }
public OBJf(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //Unknown + version (always 0) Reader.ReadBytes(8); string Header = Encoding.ASCII.GetString(Reader.ReadBytes(4)); if (Header != "fJBO") return; //Error? This shouldn't occur... m_NumEntries = Reader.ReadInt32(); for (int i = 0; i < m_NumEntries; i++) { IDPair FuncIDs = new IDPair(); FuncIDs.GuardFuncID = Reader.ReadUInt16(); FuncIDs.FunctionID = Reader.ReadUInt16(); m_FuncIDs.Add(FuncIDs); } }
/// <summary> /// Creates a FBMP instance. /// </summary> /// <param name="Chunk">The data to create this FBMP instance from.</param> public FBMP(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); m_BitmapData = new Bitmap(MemStream); }
/// <summary> /// Creates a new OBJf instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> public OBJf(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //Unknown + version (always 0) Reader.ReadBytes(8); string Header = Encoding.ASCII.GetString(Reader.ReadBytes(4)); if (Header != "fJBO") { return; //Error? This shouldn't occur... } m_NumEntries = Reader.ReadInt32(); for (int i = 0; i < m_NumEntries; i++) { IDPair FuncIDs = new IDPair(); FuncIDs.GuardFuncID = Reader.ReadUInt16(); FuncIDs.FunctionID = Reader.ReadUInt16(); m_FuncIDs.Add(FuncIDs); } }
/// <summary> /// Constructs an instance of IffChunk based on an instance of IffChunk. /// Used by classes inheriting from this class. /// </summary> /// <param name="Chunk">The IffChunk instance to construct from.</param> public IffChunk(IffChunk Chunk) { m_ID = Chunk.ID; m_Length = Chunk.Length; m_NameStr = Chunk.NameString; m_Resource = Chunk.Resource; m_PadByte = Chunk.PadByte; }
/// <summary> /// Creates a new BCON instance. /// </summary> /// <param name="Chunk">The chunk to create the BCON instance from.</param> public BCON(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_NumConstants = Reader.ReadByte(); m_Type = Reader.ReadByte(); for (byte i = 0; i < m_NumConstants; i++) { short Const = Reader.ReadInt16(); m_Constants.Add(Const); } }
/// <summary> /// Creates a new FCNS instance. /// </summary> /// <param name="Chunk">The chunk to create this FCNS instance from.</param> public FCNS(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); Reader.ReadBytes(4); //0 m_Version = Reader.ReadInt32(); Reader.ReadBytes(4); //"SNCF" m_ConstantCount = Reader.ReadUInt32(); for(int i = 0; i < m_ConstantCount; i++) { TuningConstant TConstant = new TuningConstant(); if (m_Version == 1) { TConstant.Name = ReadZeroPaddedString(Reader); byte[] Value = Reader.ReadBytes(4); //This should totally not be neccessary, but once again //Maxis has introduced the concept of 'half-empty-entries'! if (Value.Length == 0) { m_TuningConstants.Add(TConstant); break; } TConstant.Value = BitConverter.ToSingle(Value, 0); TConstant.Description = ReadZeroPaddedString(Reader); } else if (m_Version == 2) { TConstant.Name = Reader.ReadString(); TConstant.Value = Reader.ReadSingle(); TConstant.Description = Reader.ReadString(); } m_TuningConstants.Add(TConstant); } }
/// <summary> /// Creates a new FCNS instance. /// </summary> /// <param name="Chunk">The chunk to create this FCNS instance from.</param> public FCNS(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); Reader.ReadBytes(4); //0 m_Version = Reader.ReadInt32(); Reader.ReadBytes(4); //"SNCF" m_ConstantCount = Reader.ReadUInt32(); for (int i = 0; i < m_ConstantCount; i++) { TuningConstant TConstant = new TuningConstant(); if (m_Version == 1) { TConstant.Name = ReadZeroPaddedString(Reader); byte[] Value = Reader.ReadBytes(4); //This should totally not be neccessary, but once again //Maxis has introduced the concept of 'half-empty-entries'! if (Value.Length == 0) { m_TuningConstants.Add(TConstant); break; } TConstant.Value = BitConverter.ToSingle(Value, 0); TConstant.Description = ReadZeroPaddedString(Reader); } else if (m_Version == 2) { TConstant.Name = Reader.ReadString(); TConstant.Value = Reader.ReadSingle(); TConstant.Description = Reader.ReadString(); } m_TuningConstants.Add(TConstant); } }
/// <summary> /// Creates a new palettemap instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> public PaletteMap(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Colors = new Color[256]; Reader.BaseStream.Position = 16; for (int i = 0; i < 256; i++) { byte[] colors = new byte[] {}; if ((Reader.BaseStream.Length - Reader.BaseStream.Position) >= 3) m_Colors[i] = Color.FromArgb(Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte()); else m_Colors[i] = Color.FromArgb(255, 0x80, 0x80, 0x80); } Reader.Close(); }
/// <summary> /// Creates a chunk from a ResourceID and an offset in the IFF file. /// </summary> /// <param name="Resource">The ResourceID for the chunk.</param> /// <param name="offset">The offset for the chunk in the IFF file.</param> /// <returns>A new IffChunk instance.</returns> private IffChunk ToChunk(string Resource, int offset) { IffChunk Chunk = new IffChunk(Resource); Chunk.Length = Endian.SwapUInt32(m_Reader.ReadUInt32()) - 76; Chunk.ID = Endian.SwapUInt16(m_Reader.ReadUInt16()); ushort Flags = Endian.SwapUInt16(m_Reader.ReadUInt16()); Chunk.NameString = GetNameString(); if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) >= Chunk.Length) { m_Reader.BaseStream.Position = offset + 76; Chunk.Data = m_Reader.ReadBytes((int)Chunk.Length); } else { Chunk.Data = new byte[Chunk.Length]; } return(Chunk); }
/// <summary> /// Creates a new palettemap instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> public PaletteMap(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Colors = new Color[256]; Reader.BaseStream.Position = 16; for (int i = 0; i < 256; i++) { byte[] colors = new byte[] {}; if ((Reader.BaseStream.Length - Reader.BaseStream.Position) >= 3) { m_Colors[i] = Color.FromArgb(Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte()); } else { m_Colors[i] = Color.FromArgb(255, 0x80, 0x80, 0x80); } } Reader.Close(); }
/// <summary> /// Creates a new drawgroup instance. /// </summary> /// <param name="ChunkData">The data for the chunk.</param> /// <param name="Sprites">The sprites that the DGRP consists of.</param> public DrawGroup(IffChunk Chunk, List <SPR2Parser> Sprites) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_ID = ID; m_Sprites = Sprites; m_Version = Reader.ReadUInt16() - 20000; uint Count = (m_Version < 3) ? Reader.ReadUInt16() : Reader.ReadUInt32(); uint SpriteCount, DirectionFlag, Zoom; for (int i = 0; i < Count; i++) { if (m_Version < 3) { SpriteCount = Reader.ReadUInt16(); DirectionFlag = Reader.ReadByte(); Zoom = Reader.ReadByte(); } else { DirectionFlag = Reader.ReadUInt32(); Zoom = Reader.ReadUInt32(); SpriteCount = Reader.ReadUInt32(); } DrawGroupImg Image = new DrawGroupImg(SpriteCount, DirectionFlag, Zoom); for (int j = 0; j < SpriteCount; j++) { ushort Tag = 0; int PixelX = 0, PixelY = 0; uint SprID = 0, SprFrameID = 0, Flags = 0; float ZOffset = 0, XOffset = 0, YOffset = 0; if (m_Version < 3) { Tag = Reader.ReadUInt16(); SprID = Reader.ReadUInt16(); SprFrameID = Reader.ReadUInt16(); Flags = Reader.ReadUInt16(); PixelX = Reader.ReadInt16(); PixelY = Reader.ReadInt16(); if (m_Version == 1) { ZOffset = Reader.ReadUInt32(); } } else { SprID = Reader.ReadUInt32(); SprFrameID = Reader.ReadUInt32(); PixelX = Reader.ReadInt32(); PixelY = Reader.ReadInt32(); ZOffset = Reader.ReadUInt32(); Flags = Reader.ReadUInt32(); if (m_Version == 4) { XOffset = Reader.ReadUInt32(); YOffset = Reader.ReadUInt32(); } } SpriteFrame Frame = FindSpriteFrame(SprID, SprFrameID); if (Frame != null) { DrawGroupSprite Sprite = new DrawGroupSprite(Tag, Flags, new PixelOffset(PixelX, PixelY), new WorldOffset(XOffset, YOffset, ZOffset), Frame); Image.Sprites.Insert(0, Sprite); } } m_Images.Add(Image); } }
public TTAB(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_InteractionCount = Reader.ReadUInt16(); if (m_InteractionCount > 0) { m_Version = Reader.ReadUInt16(); try { long FieldValue = 0; if (m_Version == 9 || m_Version == 10) { m_CompressionCode = Reader.ReadByte(); m_FEncodingData.CompressionCode = m_CompressionCode; m_FEncodingData.FieldWidths = new byte[] { 5, 8, 13, 16, 6, 11, 21, 32 }; m_FEncodingData.EncodedDataLength = (uint)(Reader.BaseStream.Length - Reader.BaseStream.Position); m_FEncodingData.EncodedData = Reader.ReadBytes((int)m_FEncodingData.EncodedDataLength); } for (ushort i = 0; i < m_InteractionCount; i++) { if (m_Version == 9 || m_Version == 10) { Interaction Action = new Interaction(); m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); Action.ActionFuncID = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); Action.GuardFuncID = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.MotiveEntryCount = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.Flags = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.TTAID = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AttenuationCode = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AttenuationValue = (float)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AutonomyThreshold = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.JoiningIndex = (int)FieldValue; for (uint j = 0; j < Action.MotiveEntryCount; j++) { Motive MotiveEntry = new Motive(); m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.EffectRangeMinimum = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.EffectRangeMaximum = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.PersonalityModifier = (ushort)FieldValue; Action.Motives.Add(MotiveEntry); } m_Interactions.Add(Action); if(m_Version == 10) m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); //Unknown... } else if (m_Version == 5 || m_Version == 7 || m_Version == 8 || m_Version == 11) { Interaction Action = new Interaction(); Action.ActionFuncID = Reader.ReadInt16(); Action.GuardFuncID = Reader.ReadInt16(); Action.MotiveEntryCount = Reader.ReadUInt32(); Action.Flags = Reader.ReadUInt32(); Action.TTAID = Reader.ReadUInt32(); if (m_Version >= 7) Action.AttenuationCode = Reader.ReadUInt32(); Action.AttenuationValue = Reader.ReadUInt32(); Action.AutonomyThreshold = Reader.ReadUInt32(); Action.JoiningIndex = Reader.ReadInt32(); for (uint j = 0; j < Action.MotiveEntryCount; j++) { Motive MotiveEntry = new Motive(); if (m_Version >= 7) MotiveEntry.EffectRangeMinimum = Reader.ReadInt16(); MotiveEntry.EffectRangeMaximum = Reader.ReadInt16(); if(m_Version >= 7) MotiveEntry.PersonalityModifier = Reader.ReadUInt16(); Action.Motives.Add(MotiveEntry); } m_Interactions.Add(Action); if (m_Version == 11) Reader.ReadBytes(4); //Unknown. } } } catch (Exception E) { Log.LogThis("Failed parsing a TTAB chunk!\r\n" + "Version: " + m_Version + "\r\n" + "InteractionCount: " + m_InteractionCount + "\r\n" + E.ToString(), eloglevel.error); } } Reader.Close(); }
public SPR2Parser(IffChunk Chunk, List<PaletteMap> PMaps) : base(Chunk) { m_Name = Name; int[] offsets; MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Version = Reader.ReadUInt32(); //In version 1001, all frames are decompressed from the beginning, and there's no point in storing //the compressed data AS WELL as the decompressed frames...! if (m_Version == 1000) m_ChunkData = Chunk.Data; if (m_Version == 1001) { m_PaletteID = Reader.ReadUInt32(); m_FrameCount = Reader.ReadUInt32(); } else { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); } if (PMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PMaps[0]; } else m_PMap = PMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return true; } return false; }); //Some SPR2s blatantly specify the wrong ID because there's only one palettemap... if (m_PMap == null) { m_PMap = PMaps[0]; } offsets = new int[m_FrameCount]; if (m_Version == 1000) { for (int i = 0; i < m_FrameCount; i++) { offsets[i] = Reader.ReadInt32(); m_FrameOffsets.Add(offsets[i]); } } if (m_Version == 1001) { for (int l = 0; l < m_FrameCount; l++) { SpriteFrame Frame = new SpriteFrame(); Frame.Version = Reader.ReadUInt32(); Frame.Size = Reader.ReadUInt32(); Frame.Width = Reader.ReadUInt16(); Frame.Height = Reader.ReadUInt16(); Frame.Flag = Reader.ReadUInt32(); Frame.PaletteID = Reader.ReadUInt16(); Frame.TransparentPixel = m_PMap.GetColorAtIndex(Reader.ReadUInt16()); Frame.YLocation = Reader.ReadUInt16(); Frame.XLocation = Reader.ReadUInt16(); if ((SPR2Flags)Frame.Flag == SPR2Flags.HasAlphaChannel) Frame.Init(true); else Frame.Init(false); DecompressFrame(ref Frame, ref Reader); Frame.BitmapData.Unlock(true); //The bitmapdata is locked when the frame is created. m_Frames.Add(Frame); } } Reader.Close(); }
public InteractionList(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); if ((Reader.BaseStream.Length - Reader.BaseStream.Position) == 0) return; //Empty (strange, but it happens). m_NumInteractions = Reader.ReadInt16(); if ((Reader.BaseStream.Length - Reader.BaseStream.Position) == 0 || (Reader.BaseStream.Length - Reader.BaseStream.Position) < 2) return; //Too short (strange, but it happens). m_Version = Reader.ReadInt16(); if (m_NumInteractions <= 0) return; if (m_Version == 9 || m_Version == 10) { m_CompressionCode = Reader.ReadByte(); if (m_CompressionCode != 1) return; //Compressioncode should always be 1. } switch (m_Version) { case 2: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt16(); Reader.ReadInt16(); //0xA3A3 (skip) Reader.ReadInt32(); //4-byte float, no idea what it is used for. m_Interactions.Add(Interaction); } break; case 3: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt16(); Interaction.Flags = Reader.ReadInt16(); Reader.ReadInt32(); //4-byte float, no idea what it is used for. m_Interactions.Add(Interaction); } break; case 5: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 7: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.AttenuationCode = Reader.ReadInt32(); Interaction.AttenuationValue = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 8: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.AttenuationCode = Reader.ReadInt32(); Interaction.AttenuationValue = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 9: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); BitArray BArray = new BitArray(Reader.ReadBytes(2)); Interaction.ActionFunction = (short)GetShortBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.GuardFunction = (short)GetShortBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.MotiveEntries = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.Flags = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.StrTableIndex = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.AttenuationCode = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.AttenuationValue = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.Autonomy = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.JoinIndex = (int)GetLongBits(BArray); m_Interactions.Add(Interaction); } break; } Reader.Close(); }
/// <summary> /// Creates a new SPR instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> /// <param name="PMaps">The palettemaps for this SPR.</param> public SPRParser(IffChunk Chunk, List <PaletteMap> PaletteMaps) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //The two first bytes aren't used by the version... ushort FirstBytes = Reader.ReadUInt16(); if (FirstBytes == 0) { m_IsBigEndian = true; m_Version = (uint)Endian.SwapUInt16(Reader.ReadUInt16()); } else { m_Version = (uint)FirstBytes; Reader.ReadUInt16(); } //In version 1001, all frames are decompressed from the beginning, and there's no point in storing //the compressed data AS WELL as the decompressed frames...! if (m_Version != 1001) { m_ChunkData = Chunk.Data; } if (m_IsBigEndian) { if (m_Version != 1001) { m_FrameCount = Endian.SwapUInt32(Reader.ReadUInt32()); m_PaletteID = Endian.SwapUInt32(Reader.ReadUInt32()); for (uint i = 0; i < m_FrameCount; i++) { m_OffsetTable.Add(Endian.SwapUInt32(Reader.ReadUInt32())); } //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else { m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } } else { m_FrameCount = Endian.SwapUInt32(Reader.ReadUInt32()); m_PaletteID = Endian.SwapUInt32(Reader.ReadUInt32()); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else { m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } } } else { if (m_Version != 1001) { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); for (uint i = 0; i < m_FrameCount; i++) { m_OffsetTable.Add(Reader.ReadUInt32()); } //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else { m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } } else { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else { m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } } } if (m_Version == 1001) { //Framecount may be set to -1 and should be ignored... while (true) { SpriteFrame Frame = new SpriteFrame(); Frame.Version = Reader.ReadUInt32(); Frame.Size = Reader.ReadUInt32(); Reader.ReadBytes(4); //Reserved. Frame.Height = Reader.ReadUInt16(); Frame.Width = Reader.ReadUInt16(); Frame.Init(true, false); //SPR#s don't have alpha channels, but alpha is used to plot transparent pixels. DecompressFrame2(ref Frame, ref Reader); Frame.BitmapData.Unlock(true); //The bitmapdata is locked when the frame is created. m_Frames.Add(Frame); if ((Reader.BaseStream.Position == Reader.BaseStream.Length) || (Reader.BaseStream.Position - Reader.BaseStream.Length < 14)) { break; } } } Reader.Close(); }
/// <summary> /// Creates a new drawgroup instance. /// </summary> /// <param name="ChunkData">The data for the chunk.</param> /// <param name="Sprites">The sprites that the DGRP consists of.</param> public DrawGroup(IffChunk Chunk, List<SPR2Parser> Sprites) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_ID = ID; m_Sprites = Sprites; m_Version = Reader.ReadUInt16() - 20000; uint Count = (m_Version < 3) ? Reader.ReadUInt16() : Reader.ReadUInt32(); uint SpriteCount, DirectionFlag, Zoom; for (int i = 0; i < Count; i++) { if (m_Version < 3) { SpriteCount = Reader.ReadUInt16(); DirectionFlag = Reader.ReadByte(); Zoom = Reader.ReadByte(); } else { DirectionFlag = Reader.ReadUInt32(); Zoom = Reader.ReadUInt32(); SpriteCount = Reader.ReadUInt32(); } DrawGroupImg Image = new DrawGroupImg(SpriteCount, DirectionFlag, Zoom); for (int j = 0; j < SpriteCount; j++) { ushort Tag = 0; int PixelX = 0, PixelY = 0; uint SprID = 0, SprFrameID = 0, Flags = 0; float ZOffset = 0, XOffset = 0, YOffset = 0; if (m_Version < 3) { Tag = Reader.ReadUInt16(); SprID = Reader.ReadUInt16(); SprFrameID = Reader.ReadUInt16(); Flags = Reader.ReadUInt16(); PixelX = Reader.ReadInt16(); PixelY = Reader.ReadInt16(); if (m_Version == 1) ZOffset = Reader.ReadUInt32(); } else { SprID = Reader.ReadUInt32(); SprFrameID = Reader.ReadUInt32(); PixelX = Reader.ReadInt32(); PixelY = Reader.ReadInt32(); ZOffset = Reader.ReadUInt32(); Flags = Reader.ReadUInt32(); if (m_Version == 4) { XOffset = Reader.ReadUInt32(); YOffset = Reader.ReadUInt32(); } } SpriteFrame Frame = FindSpriteFrame(SprID, SprFrameID); if (Frame != null) { DrawGroupSprite Sprite = new DrawGroupSprite(Tag, Flags, new PixelOffset(PixelX, PixelY), new WorldOffset(XOffset, YOffset, ZOffset), Frame); Image.Sprites.Insert(0, Sprite); } } m_Images.Add(Image); } }
/// <summary> /// Creates a new StringTable instance. /// </summary> /// <param name="Chunk">The chunk data for this StringTable.</param> public StringTable(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //Another example of the grossness of this format; random use of big-endian numbers... byte[] FormatCodeBuf = Reader.ReadBytes(2); Array.Reverse(FormatCodeBuf); m_FormatCode = BitConverter.ToUInt16(FormatCodeBuf, 0); switch (m_FormatCode) { case 0: //Some tables are empty... LITERALLY! if (Reader.BaseStream.Position < Reader.BaseStream.Length) { m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); Str.Str = ReadPascalString(Reader); m_Strings.Add(Str); } } break; case 0xFFFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); char C; StringBuilder SB = new StringBuilder(); while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') break; } Str.Str = SB.ToString(); m_Strings.Add(Str); } break; case 0xFEFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); char C; StringBuilder SB = new StringBuilder(); //String while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') break; } Str.Str = SB.ToString(); m_Strings.Add(Str); SB = new StringBuilder(); //Comment while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') break; } } break; case 0xFDFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); Str.LanguageCode = Reader.ReadByte(); char C; StringBuilder SB = new StringBuilder(); while (true) { C = (char)Reader.ReadByte(); if (C == '\0') break; SB.Append(C); } Str.Str = SB.ToString(); C = new char(); SB = new StringBuilder(); while (true) { C = (char)Reader.ReadByte(); if (C == '\0') break; SB.Append(C); } Str.Str2 = SB.ToString(); m_Strings.Add(Str); } break; case 0xFCFF: //Only found in TSO-files! m_NumSets = Reader.ReadByte(); if (m_NumSets >= 1) { for (int i = 0; i < m_NumSets; i++) { StringSet Set = new StringSet(); Set.NumEntries = Reader.ReadInt16(); for (int j = 0; j < Set.NumEntries; j++) { // string code, then two specially-counted strings // for some reason, the language code is one below the // documented values. we adjust this here, which // unfortunately makes non-translated strings strange. StringTableString Str = new StringTableString(); Str.LanguageCode = (byte)(Reader.ReadByte() + 1); Str.Str = ReadPascalString1(Reader); Str.Str2 = ReadPascalString1(Reader); Set.Strings.Add(Str); } m_StringSets.Add(Set); } } break; } Reader.Close(); }
/// <summary> /// Creates a new BHAV instance. /// </summary> /// <param name="Chunk">The chunk to create this instance from.</param> public BHAV(IffChunk Chunk) : base(Chunk) { m_ChunkID = ChunkID; MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Instructions = new List <byte[]>(); byte[] Header = Reader.ReadBytes(12); m_Signature = (ushort)((Header[1] << 8) | Header[0]); int Count = 0; switch (m_Signature) { case 0x8000: case 0x8001: m_HeaderLength = 12; Count = (Header[3] << 8) | Header[4]; m_Locals = 0; //No locals in code; added in 8002? m_Params = 4; //I can't find this in header; always 4? break; case 0x8002: m_HeaderLength = 12; Count = (Header[3] << 8) | Header[4]; m_Type = Header[5]; m_Params = Header[6]; m_Locals = (ushort)((Header[7] << 8) | Header[8]); m_Flags = (ushort)((Header[9] << 8) | Header[10]); //Byte 11 and 12 are set to 0 in this version, we have no use for them. break; case 0x8003: m_HeaderLength = 13; byte LastHeaderByte = Reader.ReadByte(); Count = (((((LastHeaderByte << 8) | Header[11]) << 8) | Header[10]) << 8) | Header[9]; m_Type = Header[3]; m_Params = Header[4]; m_Locals = Header[5]; //Byte number 6 and 7 are unknown in this version, we have no use for them. m_Flags = (ushort)((Header[8] << 8) | Header[9]); break; } m_NumInstructions = (byte)Count; if (Count <= 0 || Count > 253) { return; } //Read all the instructions... for (int i = 0; i < Count; i++) { m_Instructions.Add(Reader.ReadBytes(12)); } }
/// <summary> /// Reads the chunks of the IFF-archive by looking for the RSMP. /// </summary> private void ReadChunks() { string Identifier = new string(m_Reader.ReadChars(60)).Replace("\0", ""); if (Identifier != "IFF FILE 2.5:TYPE FOLLOWED BY SIZE JAMIE DOORNBOS & MAXIS 1") { throw new Exception("Invalid iff file!"); } uint resMapOffset = Endian.SwapUInt32(m_Reader.ReadUInt32()); Dictionary <string, List <uint> > files = new Dictionary <string, List <uint> >(); if (resMapOffset != 0) { long pos = m_Reader.BaseStream.Position; m_Reader.BaseStream.Position = resMapOffset; m_Reader.BaseStream.Position += 76; //Skip the header. m_Reader.ReadInt32(); //Reserved uint version = m_Reader.ReadUInt32(); m_Reader.ReadInt32(); //pmsr m_Reader.ReadInt32(); //Size uint typeCount = m_Reader.ReadUInt32(); //How many types are present in this *.iff... for (uint i = 0; i < typeCount; i++) { //NOTE: For some types in some files this is empty... string typeCode = new ASCIIEncoding().GetString(m_Reader.ReadBytes(4)); if (version == 0) { //Empty RSMP... //numEntries + 1 entry without label = 13 bytes. if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < 13) { files.Clear(); FuckThisShit(ref files); break; } } else if (version == 1) { //Empty RSMP... //numEntries + 1 entry without label = 16 bytes. if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < 16) { files.Clear(); FuckThisShit(ref files); break; } } //How many entries there are... uint numEntries = m_Reader.ReadUInt32(); List <uint> offsets = new List <uint>(); for (uint j = 0; j < numEntries; j++) { if (version == 0) { //Empty RSMP... //Minimum size for an entry without a label is 9 bytes. if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < ((numEntries - j) * 9)) { files.Clear(); FuckThisShit(ref files); break; } } else if (version == 1) { //Empty RSMP... //Minimum size for an entry without a label is 12 bytes. if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < ((numEntries - j) * 12)) { files.Clear(); FuckThisShit(ref files); break; } } uint offset = m_Reader.ReadUInt32(); m_Reader.ReadInt16(); //ChunkID if (version == 1) { m_Reader.ReadInt16(); } //ChunkID m_Reader.ReadInt16(); //Flags if (version == 1) { byte Length = m_Reader.ReadByte(); if (Length > 0) { m_Reader.ReadBytes(Length); } } else { GetNameString(); } offsets.Add(offset); } if (!files.ContainsKey(typeCode)) { files.Add(typeCode, offsets); } } } else //There was no offset to the resourcemap, meaning that an RSMP probably doesn't exist. { List <KeyValuePair <string, uint> > offsets = new List <KeyValuePair <string, uint> >(); while (true) { uint offset = (uint)m_Reader.BaseStream.Position; byte[] TagBytes = m_Reader.ReadBytes(4); Array.Reverse(TagBytes); string tag = new ASCIIEncoding().GetString(TagBytes); byte[] bytes = m_Reader.ReadBytes(4); if (bytes.Length == 0) { break; } uint size = Endian.SwapUInt32(BitConverter.ToUInt32(bytes, 0)); m_Reader.BaseStream.Position += (size - 8); if (!tag.Equals("XXXX")) { offsets.Add(new KeyValuePair <string, uint>(tag, offset)); } //76 bytes is the size of a chunkheader, so don't bother reading the next one //the stream has less than 76 bytes left. if (m_Reader.BaseStream.Position == m_Reader.BaseStream.Length || (m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < 76) { break; } } List <string> typesFound = new List <string>(); foreach (KeyValuePair <string, uint> kvp in offsets) { if (!typesFound.Exists(delegate(string s) { return(s.CompareTo(kvp.Key) == 0); })) { List <KeyValuePair <string, uint> > theseChunks = offsets.FindAll(delegate(KeyValuePair <string, uint> pair) { return(pair.Key.CompareTo(kvp.Key) == 0); }); List <uint> offsetValues = new List <uint>(); foreach (KeyValuePair <string, uint> kvp2 in theseChunks) { offsetValues.Add(kvp2.Value); } if (!files.ContainsKey(kvp.Key)) { files.Add(kvp.Key, offsetValues); } typesFound.Add(kvp.Key); } } } foreach (KeyValuePair <string, List <uint> > file in files) { foreach (int offset in file.Value) { if (offset > 0) { m_Reader.BaseStream.Position = offset; byte[] Buf = m_Reader.ReadBytes(4); string StrResource = Encoding.ASCII.GetString(Buf); if (StrResource == "SPR#" || StrResource == "SPR2" || StrResource == "rsmp" || StrResource == "PALT" || StrResource == "DGRP" || StrResource == "STR#" || StrResource == "BHAV" || StrResource == "FWAV" || StrResource == "CTSS" || StrResource == "TTAB" || StrResource == "TTAs" || StrResource == "OBJf" || StrResource == "BCON" || StrResource == "TPRP" || StrResource == "TMPL" || StrResource == "TRCN" || StrResource == "Optn" || StrResource == "SLOT" || StrResource == "GLOB" || StrResource == "FBMP" || StrResource == "BMP_" || StrResource == "FCNS") { //MessageBox.Show(StrResource); IffChunk Chunk = ToChunk(StrResource, offset); //i += (int)Chunk.Length; m_Chunks.Add(Chunk); } } } } }
private byte m_Type; //Usually 0, but may be 1, 2, 3, or 22. #endregion Fields #region Constructors public BHAV(IffChunk Chunk) : base(Chunk) { m_ChunkID = ChunkID; MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Instructions = new List<byte[]>(); byte[] Header = Reader.ReadBytes(12); m_Signature = (ushort)((Header[1] << 8) | Header[0]); int Count = 0; switch (m_Signature) { case 0x8000: case 0x8001: m_HeaderLength = 12; Count = (Header[3] << 8) | Header[4]; m_Locals = 0; //No locals in code; added in 8002? m_Params = 4; //I can't find this in header; always 4? break; case 0x8002: m_HeaderLength = 12; Count = (Header[3] << 8) | Header[4]; m_Type = Header[5]; m_Params = Header[6]; m_Locals = (ushort)((Header[7] << 8) | Header[8]); m_Flags = (ushort)((Header[9] << 8) | Header[10]); //Byte 11 and 12 are set to 0 in this version, we have no use for them. break; case 0x8003: m_HeaderLength = 13; byte LastHeaderByte = Reader.ReadByte(); Count = (((((LastHeaderByte << 8) | Header[11]) << 8) | Header[10]) << 8) | Header[9]; m_Type = Header[3]; m_Params = Header[4]; m_Locals = Header[5]; //Byte number 6 and 7 are unknown in this version, we have no use for them. m_Flags = (ushort)((Header[8] << 8) | Header[9]); break; } m_NumInstructions = (byte)Count; if (Count <= 0 || Count > 253) return; //Read all the instructions... for (int i = 0; i < Count; i++) m_Instructions.Add(Reader.ReadBytes(12)); }
/// <summary> /// Creates a new SPR2 instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> /// <param name="PMaps">The palettemaps for this SPR2.</param> public SPR2Parser(IffChunk Chunk, List <PaletteMap> PMaps) : base(Chunk) { m_Name = Name; int[] offsets; MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Version = Reader.ReadUInt32(); //In version 1001, all frames are decompressed from the beginning, and there's no point in storing //the compressed data AS WELL as the decompressed frames...! if (m_Version == 1000) { m_ChunkData = Chunk.Data; } if (m_Version == 1001) { m_PaletteID = Reader.ReadUInt32(); m_FrameCount = Reader.ReadUInt32(); } else { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); } if (PMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PMaps[0]; } else { m_PMap = PMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } //Some SPR2s blatantly specify the wrong ID because there's only one palettemap... if (m_PMap == null) { m_PMap = PMaps[0]; } offsets = new int[m_FrameCount]; if (m_Version == 1000) { for (int i = 0; i < m_FrameCount; i++) { offsets[i] = Reader.ReadInt32(); m_FrameOffsets.Add(offsets[i]); } } if (m_Version == 1001) { for (int l = 0; l < m_FrameCount; l++) { SpriteFrame Frame = new SpriteFrame(); Frame.Version = Reader.ReadUInt32(); Frame.Size = Reader.ReadUInt32(); Frame.Width = Reader.ReadUInt16(); Frame.Height = Reader.ReadUInt16(); Frame.Flag = Reader.ReadUInt32(); Frame.PaletteID = Reader.ReadUInt16(); Frame.TransparentPixel = m_PMap.GetColorAtIndex(Reader.ReadUInt16()); Frame.YLocation = Reader.ReadUInt16(); Frame.XLocation = Reader.ReadUInt16(); if ((SPR2Flags)Frame.Flag == SPR2Flags.HasAlphaChannel) { Frame.Init(true, true); } else { if ((SPR2Flags)Frame.Flag == SPR2Flags.HasZBufferChannel) { Frame.Init(false, true); } else { Frame.Init(false, false); } } DecompressFrame2(ref Frame, ref Reader); Frame.BitmapData.Unlock(true); //The bitmapdata is locked when the frame is created. if (Frame.HasZBuffer) { Frame.ZBuffer.Unlock(true); //The bitmapdata is locked when the frame is created. } m_Frames.Add(Frame); } } Reader.Close(); }
public InteractionList(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); if ((Reader.BaseStream.Length - Reader.BaseStream.Position) == 0) { return; //Empty (strange, but it happens). } m_NumInteractions = Reader.ReadInt16(); if ((Reader.BaseStream.Length - Reader.BaseStream.Position) == 0 || (Reader.BaseStream.Length - Reader.BaseStream.Position) < 2) { return; //Too short (strange, but it happens). } m_Version = Reader.ReadInt16(); if (m_NumInteractions <= 0) { return; } if (m_Version == 9 || m_Version == 10) { m_CompressionCode = Reader.ReadByte(); if (m_CompressionCode != 1) { return; //Compressioncode should always be 1. } } switch (m_Version) { case 2: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt16(); Reader.ReadInt16(); //0xA3A3 (skip) Reader.ReadInt32(); //4-byte float, no idea what it is used for. m_Interactions.Add(Interaction); } break; case 3: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt16(); Interaction.Flags = Reader.ReadInt16(); Reader.ReadInt32(); //4-byte float, no idea what it is used for. m_Interactions.Add(Interaction); } break; case 5: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 7: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.AttenuationCode = Reader.ReadInt32(); Interaction.AttenuationValue = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 8: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); Interaction.ActionFunction = Reader.ReadInt16(); Interaction.GuardFunction = Reader.ReadInt16(); Interaction.MotiveEntries = Reader.ReadInt32(); Interaction.Flags = Reader.ReadInt32(); Interaction.StrTableIndex = Reader.ReadInt32(); Interaction.AttenuationCode = Reader.ReadInt32(); Interaction.AttenuationValue = Reader.ReadInt32(); Interaction.Autonomy = Reader.ReadInt32(); Interaction.JoinIndex = Reader.ReadInt32(); m_Interactions.Add(Interaction); } break; case 9: for (int i = 0; i < m_NumInteractions; i++) { TTABCore Interaction = new TTABCore(); BitArray BArray = new BitArray(Reader.ReadBytes(2)); Interaction.ActionFunction = (short)GetShortBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.GuardFunction = (short)GetShortBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.MotiveEntries = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.Flags = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.StrTableIndex = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.AttenuationCode = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.AttenuationValue = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.Autonomy = (int)GetLongBits(BArray); BArray = new BitArray(Reader.ReadBytes(4)); Interaction.JoinIndex = (int)GetLongBits(BArray); m_Interactions.Add(Interaction); } break; } Reader.Close(); }
/// <summary> /// Creates a chunk from a ResourceID and an offset in the IFF file. /// </summary> /// <param name="Resource">The ResourceID for the chunk.</param> /// <param name="offset">The offset for the chunk in the IFF file.</param> /// <returns>A new IffChunk instance.</returns> private IffChunk ToChunk(string Resource, int offset) { IffChunk Chunk = new IffChunk(Resource); Chunk.Length = Endian.SwapUInt32(m_Reader.ReadUInt32()) - 76; Chunk.ID = Endian.SwapUInt16(m_Reader.ReadUInt16()); ushort Flags = Endian.SwapUInt16(m_Reader.ReadUInt16()); Chunk.NameString = GetNameString(); if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) >= Chunk.Length) { m_Reader.BaseStream.Position = offset + 76; Chunk.Data = m_Reader.ReadBytes((int)Chunk.Length); } else Chunk.Data = new byte[Chunk.Length]; return Chunk; }
/// <summary> /// Creates a new TTAB instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> public TTAB(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_InteractionCount = Reader.ReadUInt16(); if (m_InteractionCount > 0) { m_Version = Reader.ReadUInt16(); try { long FieldValue = 0; if (m_Version == 9 || m_Version == 10) { m_CompressionCode = Reader.ReadByte(); m_FEncodingData.CompressionCode = m_CompressionCode; m_FEncodingData.FieldWidths = new byte[] { 5, 8, 13, 16, 6, 11, 21, 32 }; m_FEncodingData.EncodedDataLength = (uint)(Reader.BaseStream.Length - Reader.BaseStream.Position); m_FEncodingData.EncodedData = Reader.ReadBytes((int)m_FEncodingData.EncodedDataLength); } for (ushort i = 0; i < m_InteractionCount; i++) { if (m_Version == 9 || m_Version == 10) { Interaction Action = new Interaction(); m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); Action.ActionFuncID = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); Action.GuardFuncID = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.MotiveEntryCount = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.Flags = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.TTAID = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AttenuationCode = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AttenuationValue = (float)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.AutonomyThreshold = (uint)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); Action.JoiningIndex = (int)FieldValue; for (uint j = 0; j < Action.MotiveEntryCount; j++) { Motive MotiveEntry = new Motive(); m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.EffectRangeMinimum = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.EffectRangeMaximum = (short)FieldValue; m_FReader.DecodeField(ref m_FEncodingData, 0, ref FieldValue); MotiveEntry.PersonalityModifier = (ushort)FieldValue; Action.Motives.Add(MotiveEntry); } m_Interactions.Add(Action); if (m_Version == 10) { m_FReader.DecodeField(ref m_FEncodingData, 1, ref FieldValue); //Unknown... } } else if (m_Version == 5 || m_Version == 7 || m_Version == 8 || m_Version == 11) { Interaction Action = new Interaction(); Action.ActionFuncID = Reader.ReadInt16(); Action.GuardFuncID = Reader.ReadInt16(); Action.MotiveEntryCount = Reader.ReadUInt32(); Action.Flags = Reader.ReadUInt32(); Action.TTAID = Reader.ReadUInt32(); if (m_Version >= 7) { Action.AttenuationCode = Reader.ReadUInt32(); } Action.AttenuationValue = Reader.ReadUInt32(); Action.AutonomyThreshold = Reader.ReadUInt32(); Action.JoiningIndex = Reader.ReadInt32(); for (uint j = 0; j < Action.MotiveEntryCount; j++) { Motive MotiveEntry = new Motive(); if (m_Version >= 7) { MotiveEntry.EffectRangeMinimum = Reader.ReadInt16(); } MotiveEntry.EffectRangeMaximum = Reader.ReadInt16(); if (m_Version >= 7) { MotiveEntry.PersonalityModifier = Reader.ReadUInt16(); } Action.Motives.Add(MotiveEntry); } m_Interactions.Add(Action); if (m_Version == 11) { Reader.ReadBytes(4); //Unknown. } } } } catch (Exception E) { Log.LogThis("Failed parsing a TTAB chunk!\r\n" + "Version: " + m_Version + "\r\n" + "InteractionCount: " + m_InteractionCount + "\r\n" + E.ToString(), eloglevel.error); } } Reader.Close(); }
/// <summary> /// A PALT (palette) chunk was not found when searching through this archive's rsmp, /// so find it manually. /// </summary> private void FindPALT() { m_Reader.BaseStream.Position = 64; List <KeyValuePair <string, uint> > PALTOffsets = new List <KeyValuePair <string, uint> >(); while (true) { uint offset = (uint)m_Reader.BaseStream.Position; byte[] TagBytes = m_Reader.ReadBytes(4); Array.Reverse(TagBytes); string tag = new ASCIIEncoding().GetString(TagBytes); byte[] bytes = m_Reader.ReadBytes(4); if (bytes.Length == 0) { break; } uint size = Endian.SwapUInt32(BitConverter.ToUInt32(bytes, 0)); m_Reader.BaseStream.Position += (size - 8); if (tag.Equals("PALT")) { PALTOffsets.Add(new KeyValuePair <string, uint>(tag, offset)); } //76 bytes is the size of a chunkheader, so don't bother reading the next one //the stream has less than 76 bytes left. if (m_Reader.BaseStream.Position == m_Reader.BaseStream.Length || (m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < 76) { break; } } foreach (KeyValuePair <string, uint> KVP in PALTOffsets) { m_Reader.BaseStream.Position = KVP.Value; IffChunk Chunk = new IffChunk(KVP.Key); Chunk.Length = Endian.SwapUInt32(m_Reader.ReadUInt32()) - 76; Chunk.ID = Endian.SwapUInt16(m_Reader.ReadUInt16()); ushort Flags = Endian.SwapUInt16(m_Reader.ReadUInt16()); Chunk.NameString = GetNameString(); if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) >= Chunk.Length) { m_Reader.BaseStream.Position = KVP.Value + 76; Chunk.Data = m_Reader.ReadBytes((int)Chunk.Length); } else { Chunk.Data = new byte[Chunk.Length]; } m_PMaps.Add(new PaletteMap(Chunk)); } }
/// <summary> /// A PALT (palette) chunk was not found when searching through this archive's rsmp, /// so find it manually. /// </summary> private void FindPALT() { m_Reader.BaseStream.Position = 64; List<KeyValuePair<string, uint>> PALTOffsets = new List<KeyValuePair<string, uint>>(); while (true) { uint offset = (uint)m_Reader.BaseStream.Position; byte[] TagBytes = m_Reader.ReadBytes(4); Array.Reverse(TagBytes); string tag = new ASCIIEncoding().GetString(TagBytes); byte[] bytes = m_Reader.ReadBytes(4); if (bytes.Length == 0) break; uint size = Endian.SwapUInt32(BitConverter.ToUInt32(bytes, 0)); m_Reader.BaseStream.Position += (size - 8); if (tag.Equals("PALT")) PALTOffsets.Add(new KeyValuePair<string, uint>(tag, offset)); //76 bytes is the size of a chunkheader, so don't bother reading the next one //the stream has less than 76 bytes left. if (m_Reader.BaseStream.Position == m_Reader.BaseStream.Length || (m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) < 76) break; } foreach (KeyValuePair<string, uint> KVP in PALTOffsets) { m_Reader.BaseStream.Position = KVP.Value; IffChunk Chunk = new IffChunk(KVP.Key); Chunk.Length = Endian.SwapUInt32(m_Reader.ReadUInt32()) - 76; Chunk.ID = Endian.SwapUInt16(m_Reader.ReadUInt16()); ushort Flags = Endian.SwapUInt16(m_Reader.ReadUInt16()); Chunk.NameString = GetNameString(); if ((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) >= Chunk.Length) { m_Reader.BaseStream.Position = KVP.Value + 76; Chunk.Data = m_Reader.ReadBytes((int)Chunk.Length); } else Chunk.Data = new byte[Chunk.Length]; m_PMaps.Add(new PaletteMap(Chunk)); } }
/// <summary> /// Creates a new StringTable instance. /// </summary> /// <param name="Chunk">The chunk data for this StringTable.</param> public StringTable(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //Another example of the grossness of this format; random use of big-endian numbers... byte[] FormatCodeBuf = Reader.ReadBytes(2); Array.Reverse(FormatCodeBuf); m_FormatCode = BitConverter.ToUInt16(FormatCodeBuf, 0); switch (m_FormatCode) { case 0: //Some tables are empty... LITERALLY! if (Reader.BaseStream.Position < Reader.BaseStream.Length) { m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); Str.Str = ReadPascalString(Reader); m_Strings.Add(Str); } } break; case 0xFFFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); char C; StringBuilder SB = new StringBuilder(); while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') { break; } } Str.Str = SB.ToString(); m_Strings.Add(Str); } break; case 0xFEFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); char C; StringBuilder SB = new StringBuilder(); //String while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') { break; } } Str.Str = SB.ToString(); m_Strings.Add(Str); SB = new StringBuilder(); //Comment while (true) { C = Reader.ReadChar(); SB.Append(C); if (C == '\0') { break; } } } break; case 0xFDFF: m_NumEntries = Reader.ReadUInt16(); for (int i = 0; i < m_NumEntries; i++) { StringTableString Str = new StringTableString(); Str.LanguageCode = Reader.ReadByte(); char C; StringBuilder SB = new StringBuilder(); while (true) { C = (char)Reader.ReadByte(); if (C == '\0') { break; } SB.Append(C); } Str.Str = SB.ToString(); C = new char(); SB = new StringBuilder(); while (true) { C = (char)Reader.ReadByte(); if (C == '\0') { break; } SB.Append(C); } Str.Str2 = SB.ToString(); m_Strings.Add(Str); } break; case 0xFCFF: //Only found in TSO-files! m_NumSets = Reader.ReadByte(); if (m_NumSets >= 1) { for (int i = 0; i < m_NumSets; i++) { StringSet Set = new StringSet(); Set.NumEntries = Reader.ReadInt16(); for (int j = 0; j < Set.NumEntries; j++) { // string code, then two specially-counted strings // for some reason, the language code is one below the // documented values. we adjust this here, which // unfortunately makes non-translated strings strange. StringTableString Str = new StringTableString(); Str.LanguageCode = (byte)(Reader.ReadByte() + 1); Str.Str = ReadPascalString1(Reader); Str.Str2 = ReadPascalString1(Reader); Set.Strings.Add(Str); } m_StringSets.Add(Set); } } break; } Reader.Close(); }
/// <summary> /// Casts a chunk to an OBJD instance. /// </summary> /// <param name="Chunk">The chunk to cast.</param> private void ToOBJD(IffChunk Chunk) { OBJD Obj = new OBJD(Chunk.Data, Chunk.ID); m_OBJDs.Add(Obj); }
/// <summary> /// Creates a new SPR instance. /// </summary> /// <param name="Chunk">The data for the chunk.</param> /// <param name="PMaps">The palettemaps for this SPR.</param> public SPRParser(IffChunk Chunk, List<PaletteMap> PaletteMaps) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); //The two first bytes aren't used by the version... ushort FirstBytes = Reader.ReadUInt16(); if (FirstBytes == 0) { m_IsBigEndian = true; m_Version = (uint)Endian.SwapUInt16(Reader.ReadUInt16()); } else { m_Version = (uint)FirstBytes; Reader.ReadUInt16(); } //In version 1001, all frames are decompressed from the beginning, and there's no point in storing //the compressed data AS WELL as the decompressed frames...! if (m_Version != 1001) m_ChunkData = Chunk.Data; if (m_IsBigEndian) { if (m_Version != 1001) { m_FrameCount = Endian.SwapUInt32(Reader.ReadUInt32()); m_PaletteID = Endian.SwapUInt32(Reader.ReadUInt32()); for (uint i = 0; i < m_FrameCount; i++) m_OffsetTable.Add(Endian.SwapUInt32(Reader.ReadUInt32())); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return true; } return false; }); } else { m_FrameCount = Endian.SwapUInt32(Reader.ReadUInt32()); m_PaletteID = Endian.SwapUInt32(Reader.ReadUInt32()); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return true; } return false; }); } } else { if (m_Version != 1001) { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); for (uint i = 0; i < m_FrameCount; i++) m_OffsetTable.Add(Reader.ReadUInt32()); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return true; } return false; }); } else { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); //Find and set the correct palettemap... if (PaletteMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PaletteMaps[0]; } else m_PMap = PaletteMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return true; } return false; }); } } if (m_Version == 1001) { //Framecount may be set to -1 and should be ignored... while(true) { SpriteFrame Frame = new SpriteFrame(); Frame.Version = Reader.ReadUInt32(); Frame.Size = Reader.ReadUInt32(); Reader.ReadBytes(4); //Reserved. Frame.Height = Reader.ReadUInt16(); Frame.Width = Reader.ReadUInt16(); Frame.Init(true, false); //SPR#s don't have alpha channels, but alpha is used to plot transparent pixels. DecompressFrame2(ref Frame, ref Reader); Frame.BitmapData.Unlock(true); //The bitmapdata is locked when the frame is created. m_Frames.Add(Frame); if ((Reader.BaseStream.Position == Reader.BaseStream.Length) || (Reader.BaseStream.Position - Reader.BaseStream.Length < 14)) break; } } Reader.Close(); }
/// <summary> /// Creates a new BMP_ file. /// </summary> /// <param name="Chunk">The chunk to create the BMP_ file from.</param> public BMP_(IffChunk Chunk) : base(Chunk) { MemoryStream MemStream = new MemoryStream(Chunk.Data); m_BitmapData = new Bitmap(MemStream); }