An IFF is made up of chunks.
示例#1
0
        public void SetActiveResource(IffChunk chunk, GameIffResource res)
        {
            GraphicChunk = (SPR2)chunk;
            ActiveIff = res;

            FrameList.Items.Clear();
            for (int i=0; i< GraphicChunk.Frames.Length / 3; i++)
            {
                FrameList.Items.Add("Rotation " + i);
            }

            bool hasFrames = (FrameList.Items.Count > 0);
            Graphics = null;
            if (hasFrames) FrameList.SelectedIndex = 0;
            else
            {
                SPRBox1.Image = null;
                SPRBox2.Image = null;
                SPRBox3.Image = null;
            }
            DeleteButton.Enabled = hasFrames;
            ImportButton.Enabled = hasFrames;
            ExportButton.Enabled = hasFrames;
            ImportAll.Enabled = hasFrames;
            ExportAll.Enabled = hasFrames;
        }
示例#2
0
        public void MoveAndSwap(IffChunk chunk, ushort targID)
        {
            if (chunk.ChunkID == targID)
            {
                return;
            }
            var    type = chunk.GetType();
            object targ = null;

            if (ByChunkId.ContainsKey(type))
            {
                ByChunkId[type].TryGetValue(targID, out targ);
            }

            var tChunk = (IffChunk)targ;

            if (tChunk != null)
            {
                RemoveChunk(tChunk);
            }
            var oldID = chunk.ChunkID;

            RemoveChunk(chunk);
            chunk.ChunkID = targID;
            AddChunk(chunk);
            if (tChunk != null)
            {
                tChunk.ChunkID = oldID;
                AddChunk(tChunk);
            }
        }
示例#3
0
 public ResAction(UIResActionDelegate action, IffChunk chunk, bool causesChange, AutoResetEvent signal)
 {
     Action = action;
     Chunk = chunk;
     Signal = signal;
     CausesChange = causesChange;
 }
示例#4
0
        public void WriteChunk(IoWriter io,IffChunk c)
        {
            var typeString = CHUNK_TYPES.FirstOrDefault(x => x.Value == c.GetType()).Key;

            io.WriteCString((typeString == null) ? c.ChunkType : typeString,4);

            byte[] data;
            using (var cstr = new MemoryStream())
            {
                if (c.Write(this,cstr))
                {
                    data = cstr.ToArray();
                }
                else
                {
                    data = c.OriginalData;
                }
            }

            //todo: exporting PIFF as IFF SHOULD NOT DO THIS
            c.OriginalData = data; //if we revert, it is to the last save.
            c.RuntimeInfo  = ChunkRuntimeState.Normal;

            io.WriteUInt32((uint)data.Length + 76);
            io.WriteUInt16(c.ChunkID);
            io.WriteUInt16(c.ChunkFlags);
            io.WriteCString(c.ChunkLabel,64);
            io.WriteBytes(data);
        }
示例#5
0
        public void RemoveChunk(IffChunk chunk)
        {
            var type = chunk.GetType();

            ByChunkId[type].Remove(chunk.ChunkID);
            ByChunkType[type].Remove(chunk);
        }
示例#6
0
 public void FullRemoveChunk(IffChunk chunk)
 {
     //register this chunk as one that has been hard removed
     if (!chunk.AddedByPatch)
     {
         RemovedOriginal.Add(chunk);
     }
     RemoveChunk(chunk);
 }
示例#7
0
        public IffChunk AddChunk(Stream stream,IoBuffer io,bool add)
        {
            var chunkType     = io.ReadCString(4);
            var chunkSize     = io.ReadUInt32();
            var chunkID       = io.ReadUInt16();
            var chunkFlags    = io.ReadUInt16();
            var chunkLabel    = io.ReadCString(64).TrimEnd('\0');
            var chunkDataSize = chunkSize - 76;

            /** Do we understand this chunk type? **/
            if (!CHUNK_TYPES.ContainsKey(chunkType))
            {
                /** Skip it! **/
                io.Skip(Math.Min(chunkDataSize,stream.Length - stream.Position - 1));  //if the chunk is invalid, it will likely provide a chunk size beyond the limits of the file. (walls2.iff)
                return(null);
            }
            else
            {
                Type     chunkClass = CHUNK_TYPES[chunkType];
                IffChunk newChunk   = (IffChunk)Activator.CreateInstance(chunkClass);
                newChunk.ChunkID    = chunkID;
                newChunk.OriginalID = chunkID;
                newChunk.ChunkFlags = chunkFlags;
                newChunk.ChunkLabel = chunkLabel;
                newChunk.ChunkType  = chunkType;
                newChunk.ChunkData  = io.ReadBytes(chunkDataSize);

                if (RetainChunkData)
                {
                    newChunk.OriginalLabel = chunkLabel;
                    newChunk.OriginalData  = newChunk.ChunkData;
                }

                if (add)
                {
                    newChunk.ChunkParent = this;

                    if (!ByChunkType.ContainsKey(chunkClass))
                    {
                        ByChunkType.Add(chunkClass,new List <object>());
                    }
                    if (!ByChunkId.ContainsKey(chunkClass))
                    {
                        ByChunkId.Add(chunkClass,new Dictionary <ushort,object>());
                    }

                    ByChunkType[chunkClass].Add(newChunk);
                    if (!ByChunkId[chunkClass].ContainsKey(chunkID))
                    {
                        ByChunkId[chunkClass].Add(chunkID,newChunk);
                    }
                }
                return(newChunk);
            }
        }
示例#8
0
 public void DiscardChange(IffChunk chunk)
 {
     lock (this)
     {
         UnregisterObjects(chunk.ChunkParent);
         chunk.ChunkParent.Revert(chunk);
         if (chunk.ChunkParent.ListAll().Count(x => x.RuntimeInfo == ChunkRuntimeState.Modified || x.RuntimeInfo == ChunkRuntimeState.Delete) == 0)
             ChangedFiles.Remove(chunk.ChunkParent);
         RegisterObjects(chunk.ChunkParent);
     }
 }
示例#9
0
        public IffNameDialog(IffChunk chunk, bool newChunk)
        {
            InitializeComponent();

            Chunk = chunk;
            ChunkLabelEntry.Text = chunk.ChunkLabel;
            NewChunk = newChunk;

            if (chunk is BHAV && chunk.ChunkParent.RuntimeInfo.UseCase == IffUseCase.Object)
                ChunkIDEntry.Minimum = 4096;

            ChunkIDEntry.Value = Math.Max(ChunkIDEntry.Minimum, Math.Min(ChunkIDEntry.Maximum, chunk.ChunkID));
        }
示例#10
0
        public void AddChunk(IffChunk chunk)
        {
            var type = chunk.GetType();

            chunk.ChunkParent = this;

            if (!ByChunkType.ContainsKey(type))
            {
                ByChunkType.Add(type, new List <object>());
            }
            if (!ByChunkId.ContainsKey(type))
            {
                ByChunkId.Add(type, new Dictionary <ushort, object>());
            }

            ByChunkId[type].Add(chunk.ChunkID, chunk);
            ByChunkType[type].Add(chunk);
        }
示例#11
0
 public void SetSelectors(OBJD objd, IffChunk active, OBJDSelector[] selectors)
 {
     Active = active;
     Definition = objd;
     SelectButton.Dock = DockStyle.Fill;
     SelectCombo.Dock = DockStyle.Fill;
     SelectButton.Visible = selectors.Length == 1;
     SelectCombo.Visible = selectors.Length > 1;
     Selectors = selectors;
     if (selectors.Length > 1)
     {
         SelectCombo.Items.Clear();
         SelectCombo.Items.Add("-- Not Selected --");
         int i = 1;
         OwnChange = true;
         SelectCombo.SelectedIndex = 0;
         foreach (var sel in selectors)
         {
             SelectCombo.Items.Add(sel);
             if (sel.FieldName != null && objd.GetPropertyByName<ushort>(sel.FieldName) == active.ChunkID)
                 SelectCombo.SelectedIndex = i;
             i++;
         }
         OwnChange = false;
     } else if (selectors.Length > 0)
     {
         var sel = selectors[0];
         if (sel.FieldName != null && objd.GetPropertyByName<ushort>(sel.FieldName) == active.ChunkID)
         {
             SelectButton.Text = "Selected as " + sel.Name;
             SelectButton.Enabled = false;
         } else
         {
             SelectButton.Text = "Select as " + sel.Name;
             SelectButton.Enabled = true;
         }
     }
     else
     {
         Enabled = false;
         Visible = false;
     }
 }
示例#12
0
        private T prepare <T>(object input)
        {
            IffChunk chunk = (IffChunk)input;

            if (chunk.ChunkProcessed != true)
            {
                lock (chunk)
                {
                    if (chunk.ChunkProcessed != true)
                    {
                        using (var stream = new MemoryStream(chunk.ChunkData))
                        {
                            chunk.Read(this,stream);
                            chunk.ChunkData      = null;
                            chunk.ChunkProcessed = true;
                        }
                    }
                }
            }
            return((T)input);
        }
示例#13
0
 public void SetActiveResource(IffChunk chunk, GameIffResource res)
 {
     ActiveString = (STR)chunk;
     UpdateStrings();
 }
示例#14
0
        public static PIFFEntry MakeChunkDiff(IffChunk chk)
        {
            var e = new PIFFEntry { Type = chk.ChunkType, ChunkID = chk.OriginalID, NewChunkID = chk.ChunkID };
            if (chk == null)
            {
                e.Delete = true;
                return e;
            }

            byte[] newData = null;
            using (var stream = new MemoryStream())
            {
                if (!chk.Write(chk.ChunkParent, stream))
                {
                    return null; //use original
                }
                newData = stream.ToArray();
            }

            e.ChunkLabel = (chk.OriginalLabel==chk.ChunkLabel)?"":chk.ChunkLabel;
            e.ChunkFlags = chk.ChunkFlags;
            e.NewDataSize = (uint)newData.Length;

            //encode difference as sequence of changes
            var oldData = chk.OriginalData;
            var patches = new List<PIFFPatch>();

            int i;
            for (i=0; i<newData.Length; i += 1000)
            {
                if (i >= oldData.Length)
                {
                    //no more comparisons, just add the remainder
                    var remain = new byte[newData.Length-i];
                    Array.Copy(newData, i, remain, 0, remain.Length);
                    patches.Add(new PIFFPatch
                    {
                        Mode = PIFFPatchMode.Add,
                        Data = remain,
                        Offset = (uint)i,
                        Size = (uint)remain.Length
                    });
                    break;
                }

                //dynamic programming matrix.
                int m = Math.Min(1000, Math.Max(0, newData.Length - i))+1;
                int n = Math.Min(1000, Math.Max(0, oldData.Length - i))+1;
                ushort[,] comp = new ushort[m, n];
                for (int x=1; x<m; x++)
                {
                    for (int y=1; y<n; y++)
                    {
                        if (newData[i+x-1] == oldData[i + y -1]) comp[x, y] = (ushort)(comp[x - 1, y - 1] + 1);
                        else comp[x, y] = Math.Max(comp[x, y - 1], comp[x - 1, y]);
                    }
                }

                var changes = new Stack<byte>();
                //backtrack through compare
                {
                    int x = m-1, y = n-1;
                    while (true)
                    {
                        if (x>0 && y>0 && newData[i + x -1] == oldData[i + y -1])
                        {
                            x--; y--; changes.Push(0); //no change
                        } else if (y>0 && (x==0 || comp[x,y-1] >= comp[x-1,y]))
                        {
                            y--; changes.Push(2); //remove
                        } else if (x>0 && (y==0 || comp[x,y-1] < comp[x-1,y]))
                        {
                            x--; changes.Push(1); //add
                        } else
                        {
                            break;
                        }
                    }
                }

                byte lastC = 0;
                PIFFPatch curr = null;
                List<byte> addArray = null;
                int ptr = 0;
                foreach (var c in changes)
                {
                    if (c != lastC && curr != null)
                    {
                        if (lastC == 1) curr.Data = addArray.ToArray();
                        patches.Add(curr);
                        curr = null;
                    }
                    if (c == 0) ptr++;
                    else if (c == 1)
                    {
                        if (lastC != 1)
                        {
                            curr = new PIFFPatch { Mode = PIFFPatchMode.Add, Offset = (uint)(i + ptr), Size = 1 };
                            addArray = new List<byte>();
                            addArray.Add(newData[i + ptr]);
                        }
                        else
                        {
                            curr.Size++;
                            addArray.Add(newData[i + ptr]);
                        }
                        ptr++;
                    }
                    else
                    {
                        if (lastC != 2)
                            curr = new PIFFPatch { Mode = PIFFPatchMode.Remove, Offset = (uint)(i + ptr), Size = 1 };
                        else
                            curr.Size++;
                    }
                    lastC = c;
                }

                if (curr != null)
                {
                    if (lastC == 1) curr.Data = addArray.ToArray();
                    patches.Add(curr);
                }

                if (m < n)
                {
                    //remainder on src to be removed
                    patches.Add(new PIFFPatch { Mode = PIFFPatchMode.Remove, Offset = (uint)(i+ptr), Size = (uint)(n-m) });
                }
                /*else if (m != n)
                {
                    //remainder on dest to be added
                    var remain = new byte[m-n];
                    Array.Copy(newData, i+ptr, remain, 0, remain.Length);
                    patches.Add(new PIFFPatch
                    {
                        Mode = PIFFPatchMode.Add,
                        Data = remain,
                        Offset = (uint)(i+ ptr),
                        Size = (uint)remain.Length
                    });
                }*/
            }

            if (oldData.Length > i)
            {
                //ran out of new data, but old is still going. Remove the remainder.
                patches.Add(new PIFFPatch
                {
                    Mode = PIFFPatchMode.Remove,
                    Offset = (uint)newData.Length,
                    Size = (uint)(oldData.Length - i)
                });
            }

            e.Patches = patches.ToArray();

            return e;
        }
示例#15
0
 public ResAction(UIResActionDelegate action, IffChunk chunk)
     : this(action, chunk, true, null)
 {
 }
示例#16
0
 public ResAction(UIResActionDelegate action, IffChunk chunk, bool causesChange)
     : this(action, chunk, causesChange, null)
 {
 }
示例#17
0
        /// <summary>
        /// Reads an IFF from a stream.
        /// </summary>
        /// <param name="stream">The stream to read from.</param>
        public void Read(Stream stream)
        {
            using (var io = IoBuffer.FromStream(stream,ByteOrder.BIG_ENDIAN))
            {
                var identifier = io.ReadCString(60,false).Replace("\0","");
                if (identifier != "IFF FILE 2.5:TYPE FOLLOWED BY SIZE JAMIE DOORNBOS & MAXIS 1")
                {
                    throw new Exception("Invalid iff file!");
                }

                var rsmpOffset = io.ReadUInt32();

                while (io.HasMore)
                {
                    var chunkType     = io.ReadCString(4);
                    var chunkSize     = io.ReadUInt32();
                    var chunkID       = io.ReadUInt16();
                    var chunkFlags    = io.ReadUInt16();
                    var chunkLabel    = io.ReadCString(64).TrimEnd('\0');
                    var chunkDataSize = chunkSize - 76;

                    /** Do we understand this chunk type? **/
                    if (!CHUNK_TYPES.ContainsKey(chunkType))
                    {
                        /** Skip it! **/
                        io.Skip(Math.Min(chunkDataSize,stream.Length - stream.Position - 1));  //if the chunk is invalid, it will likely provide a chunk size beyond the limits of the file. (walls2.iff)
                    }
                    else
                    {
                        Type     chunkClass = CHUNK_TYPES[chunkType];
                        IffChunk newChunk   = (IffChunk)Activator.CreateInstance(chunkClass);
                        newChunk.ChunkID    = chunkID;
                        newChunk.OriginalID = chunkID;
                        newChunk.ChunkFlags = chunkFlags;
                        newChunk.ChunkLabel = chunkLabel;
                        newChunk.ChunkType  = chunkType;
                        newChunk.ChunkData  = io.ReadBytes(chunkDataSize);
                        if (RETAIN_CHUNK_DATA)
                        {
                            newChunk.OriginalLabel = chunkLabel;
                            newChunk.OriginalData  = newChunk.ChunkData;
                        }
                        newChunk.ChunkParent = this;

                        if (!ByChunkType.ContainsKey(chunkClass))
                        {
                            ByChunkType.Add(chunkClass,new List <object>());
                        }
                        if (!ByChunkId.ContainsKey(chunkClass))
                        {
                            ByChunkId.Add(chunkClass,new Dictionary <ushort,object>());
                        }

                        ByChunkType[chunkClass].Add(newChunk);
                        if (!ByChunkId[chunkClass].ContainsKey(chunkID))
                        {
                            ByChunkId[chunkClass].Add(chunkID,newChunk);
                        }
                    }
                }
            }
        }
示例#18
0
 public void GotoResource(IffChunk chunk)
 {
     GotoResource(chunk.GetType(), chunk.ChunkID);
 }
示例#19
0
 public void ChunkChanged(IffChunk chunk)
 {
     chunk.RuntimeInfo = ChunkRuntimeState.Modified;
     chunk.ChunkParent.RuntimeInfo.Dirty = true;
     IffChanged(chunk.ChunkParent);
 }
示例#20
0
 public void SetActiveResource(IffChunk chunk, GameIffResource res)
 {
     ActiveRes = chunk;
 }
示例#21
0
        public void SetActiveResource(IffChunk chunk, GameIffResource res)
        {
            Resource = res;
            Strings = res.Get<TTAs>(chunk.ChunkID);
            ActiveTTAB = (TTAB)chunk;

            if (Strings == null)
            {
                //we have a problem... make us some strings!
                Strings = new TTAs();
                Strings.ChunkLabel = chunk.ChunkLabel;
                Strings.ChunkID = chunk.ChunkID;
                Strings.ChunkProcessed = true;
                res.MainIff.AddChunk(Strings);
            }

            UpdateListing();
            UpdateSelection(-1);
        }
示例#22
0
 public List<ObjectResourceEntry> GetResList(IffChunk[] list)
 {
     var result = new List<ObjectResourceEntry>();
     foreach (var item in list)
     {
         var chunk = (IffChunk)item;
         result.Add(new ObjectResourceEntry(chunk.ChunkLabel, chunk.ChunkID));
     }
     return result;
 }
示例#23
0
 public void SetActiveResource(IffChunk chunk, GameIffResource res)
 {
     ActiveChunk = (BHAV)chunk;
     ActiveMeta = res.Get<TPRP>(chunk.ChunkID);
     RefreshDisplay();
 }