Example #1
0
        public void Render()
        {
            EntryList.Items.Clear();

            PIFFName.Enabled    = ActivePIFF != null;
            PIFFComment.Enabled = ActivePIFF != null;
            if (ActivePIFF != null)
            {
                var piffs = ActivePIFF.List <PIFF>();
                if ((piffs?.Count ?? 0) == 0)
                {
                    RenderEmpty(); return;
                }
                var piff = piffs[0];
                ActivePIFFChunk = piff;

                PIFFName.Text    = ActivePIFF.Filename;
                PIFFComment.Text = piff.Comment;

                PIFFBox.Enabled = true;

                foreach (var entry in piff.Entries)
                {
                    EntryList.Items.Add(new PIFFListItem(entry, ActiveIff));
                }
            }
            else
            {
                PIFFName.Text    = "None";
                PIFFComment.Text = "Make changes and save then using the volcanic main window to view or edit the PIFF.";
            }
        }
Example #2
0
        private static string FindComment(IffChunk chunk, PIFF oldPIFF)
        {
            var oldEntry = oldPIFF?.Entries?.FirstOrDefault(entry =>
                                                            entry.Type == chunk.ChunkType &&
                                                            ((chunk.AddedByPatch) ? chunk.ChunkID : chunk.OriginalID) == entry.ChunkID);

            return(oldEntry?.Comment ?? "");
        }
Example #3
0
        private static Dictionary <string, bool> IsPIFFUser; //if a piff is User, all other piffs for that file are ignored.

        public static void Init(string basePath)
        {
            PIFFsByName = new Dictionary <string, List <IffFile> >();
            IsPIFFUser  = new Dictionary <string, bool>();

            //Directory.CreateDirectory(basePath);
            if (Directory.Exists("Content/Patch"))
            {
                string[] paths = Directory.GetFiles(basePath, "*.piff", SearchOption.AllDirectories);
                for (int i = 0; i < paths.Length; i++)
                {
                    string entry    = paths[i].Replace('\\', '/');
                    bool   user     = entry.Contains("User/");
                    string filename = Path.GetFileName(entry);

                    IffFile piffFile = new IffFile(entry);
                    PIFF    piff     = piffFile.List <PIFF>()[0];

                    if (IsPIFFUser.ContainsKey(piff.SourceIff))
                    {
                        var old = IsPIFFUser[piff.SourceIff];
                        if (old != user)
                        {
                            if (user)
                            {
                                //remove old piffs, as they have been overwritten by this user piff.
                                PIFFsByName[piff.SourceIff].Clear();
                                IsPIFFUser[piff.SourceIff] = true;
                            }
                            else
                            {
                                continue; //a user piff exists. ignore these ones.
                            }
                        }
                    }
                    else
                    {
                        IsPIFFUser.Add(piff.SourceIff, user);
                    }

                    if (!PIFFsByName.ContainsKey(piff.SourceIff))
                    {
                        PIFFsByName.Add(piff.SourceIff, new List <IffFile>());
                    }
                    PIFFsByName[piff.SourceIff].Add(piffFile);
                }
            }
        }
Example #4
0
        public void Patch(IffFile piffFile)
        {
            if (RuntimeInfo.State == IffRuntimeState.ReadOnly)
            {
                RuntimeInfo.State = IffRuntimeState.PIFFPatch;
            }
            var piff = piffFile.List <PIFF>()[0];

            CurrentPIFF = piff;

            //patch existing chunks using the PIFF chunk
            //also delete chunks marked for deletion

            var moveChunks = new List <IffChunk>();
            var newIDs     = new List <ushort>();

            foreach (var e in piff.Entries)
            {
                var type = CHUNK_TYPES[e.Type];

                Dictionary <ushort, object> chunks = null;
                ByChunkId.TryGetValue(type, out chunks);
                if (chunks == null)
                {
                    continue;
                }
                object objC = null;
                chunks.TryGetValue(e.ChunkID, out objC);
                if (objC == null)
                {
                    continue;
                }

                var chunk = (IffChunk)objC;
                if (e.EntryType == PIFFEntryType.Remove)
                {
                    FullRemoveChunk(chunk); //removed by PIFF
                }
                else if (e.EntryType == PIFFEntryType.Patch)
                {
                    chunk.ChunkData      = e.Apply(chunk.ChunkData ?? chunk.OriginalData);
                    chunk.ChunkProcessed = false;
                    if (e.ChunkLabel != "")
                    {
                        chunk.ChunkLabel = e.ChunkLabel;
                    }
                    chunk.RuntimeInfo = ChunkRuntimeState.Patched;

                    if (e.ChunkID != e.NewChunkID)
                    {
                        moveChunks.Add(chunk);
                        newIDs.Add(e.NewChunkID);
                    }
                }
            }

            for (int i = 0; i < moveChunks.Count; i++)
            {
                MoveAndSwap(moveChunks[i], newIDs[i]);
            }

            //add chunks present in the piff to the original file
            foreach (var typeG in piffFile.ByChunkType)
            {
                if (typeG.Key == typeof(PIFF))
                {
                    continue;
                }
                foreach (var res in typeG.Value)
                {
                    var chunk = (IffChunk)res;
                    chunk.AddedByPatch = true;
                    if (!ByChunkId.ContainsKey(chunk.GetType()) || !ByChunkId[chunk.GetType()].ContainsKey(chunk.ChunkID))
                    {
                        this.AddChunk(chunk);
                    }
                }
            }
        }
        public static IffFile GeneratePiff(IffFile iff, HashSet <Type> allowedTypes, HashSet <Type> disallowedTypes)
        {
            var piffFile = new IffFile();

            var piff = new PIFF();

            piff.SourceIff = iff.Filename;
            var entries = new List <PIFFEntry>();
            var chunks  = iff.ListAll();

            //write removals first
            foreach (var c in iff.RemovedOriginal)
            {
                lock (c)
                {
                    if ((allowedTypes == null || allowedTypes.Contains(c.GetType())) &&
                        (disallowedTypes == null || !disallowedTypes.Contains(c.GetType())))
                    {
                        entries.Add(new PIFFEntry {
                            Type       = c.ChunkType, ChunkID = c.OriginalID, Delete = true,
                            ChunkLabel = c.ChunkLabel, ChunkFlags = c.ChunkFlags
                        });
                    }
                }
            }

            foreach (var c in chunks)
            {
                lock (c)
                {
                    if ((allowedTypes == null || allowedTypes.Contains(c.GetType())) &&
                        (disallowedTypes == null || !disallowedTypes.Contains(c.GetType())))
                    {
                        if (c.AddedByPatch)
                        {
                            //this chunk has been newly added.
                            var oldParent = c.ChunkParent;
                            piffFile.AddChunk(c);
                            c.ChunkParent = oldParent;
                        }
                        else if ((c.RuntimeInfo == ChunkRuntimeState.Modified || c.RuntimeInfo == ChunkRuntimeState.Patched))
                        {
                            var chunkD = MakeChunkDiff(c);
                            if (chunkD != null && (chunkD.Patches.Length > 0 || c.OriginalLabel != c.ChunkLabel || c.OriginalID != c.ChunkID))
                            {
                                entries.Add(chunkD);
                            }
                            c.RuntimeInfo = ChunkRuntimeState.Patched;
                        }
                    }
                }
            }
            if (entries.Count == 0)
            {
                return(null);                    //no patch data...
            }
            piff.Entries        = entries.ToArray();
            piff.ChunkID        = 256;
            piff.ChunkLabel     = (piff.SourceIff + " patch");
            piff.ChunkProcessed = true;

            piffFile.AddChunk(piff);
            piffFile.Filename = piff.SourceIff.Substring(0, piff.SourceIff.Length - 4) + ".piff";
            return(piffFile);
        }
Example #6
0
        public static IffFile GeneratePiff(IffFile iff, HashSet <Type> allowedTypes, HashSet <Type> disallowedTypes, PIFF oldPIFF)
        {
            var piffFile = new IffFile();

            var piff = new PIFF();

            piff.SourceIff = iff.Filename;
            if (oldPIFF != null)
            {
                piff.Comment = oldPIFF.Comment;
            }
            var entries = new List <PIFFEntry>();
            var chunks  = iff.ListAll();

            //write removals first
            foreach (var c in iff.RemovedOriginal)
            {
                lock (c)
                {
                    if ((allowedTypes == null || allowedTypes.Contains(c.GetType())) &&
                        (disallowedTypes == null || !disallowedTypes.Contains(c.GetType())))
                    {
                        entries.Add(new PIFFEntry {
                            Type       = c.ChunkType, ChunkID = c.OriginalID, EntryType = PIFFEntryType.Remove,
                            ChunkLabel = c.ChunkLabel, ChunkFlags = c.ChunkFlags, Comment = FindComment(c, oldPIFF)
                        });
                    }
                }
            }

            bool anyAdded = false;

            foreach (var c in chunks)
            {
                //find a comment for this chunk
                lock (c)
                {
                    if ((allowedTypes == null || allowedTypes.Contains(c.GetType())) &&
                        (disallowedTypes == null || !disallowedTypes.Contains(c.GetType())))
                    {
                        if (c.AddedByPatch)
                        {
                            //this chunk has been newly added.
                            var oldParent = c.ChunkParent;
                            anyAdded = true;
                            piffFile.AddChunk(c);
                            c.ChunkParent = oldParent;

                            //make an entry for it!
                            entries.Add(new PIFFEntry()
                            {
                                ChunkID     = c.ChunkID,
                                ChunkLabel  = c.ChunkLabel,
                                ChunkFlags  = c.ChunkFlags,
                                EntryType   = PIFFEntryType.Add,
                                NewDataSize = (uint)(c.ChunkData?.Length ?? 0),
                                Type        = c.ChunkType,
                                Comment     = FindComment(c, oldPIFF)
                            });
                        }
                        else if ((c.RuntimeInfo == ChunkRuntimeState.Modified || c.RuntimeInfo == ChunkRuntimeState.Patched))
                        {
                            var chunkD = MakeChunkDiff(c);
                            if (chunkD != null && (chunkD.Patches.Length > 0 || c.OriginalLabel != c.ChunkLabel || c.OriginalID != c.ChunkID))
                            {
                                chunkD.Comment = FindComment(c, oldPIFF);
                                entries.Add(chunkD);
                            }
                            c.RuntimeInfo = ChunkRuntimeState.Patched;
                        }
                    }
                }
            }
            if (entries.Count == 0 && !anyAdded)
            {
                return(null);                                 //no patch data...
            }
            piff.Entries        = entries.ToArray();
            piff.ChunkID        = 256;
            piff.ChunkLabel     = (piff.SourceIff + " patch");
            piff.ChunkProcessed = true;

            piffFile.AddChunk(piff);
            piffFile.Filename = (oldPIFF != null) ? oldPIFF.ChunkParent.Filename : null; // (piff.SourceIff.Substring(0, piff.SourceIff.Length - 4)+".piff")
            return(piffFile);
        }