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."; } }
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 ?? ""); }
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); } } }
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); }
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); }