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; }
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); } }
public ResAction(UIResActionDelegate action, IffChunk chunk, bool causesChange, AutoResetEvent signal) { Action = action; Chunk = chunk; Signal = signal; CausesChange = causesChange; }
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); }
public void RemoveChunk(IffChunk chunk) { var type = chunk.GetType(); ByChunkId[type].Remove(chunk.ChunkID); ByChunkType[type].Remove(chunk); }
public void FullRemoveChunk(IffChunk chunk) { //register this chunk as one that has been hard removed if (!chunk.AddedByPatch) { RemovedOriginal.Add(chunk); } RemoveChunk(chunk); }
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); } }
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); } }
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)); }
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); }
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; } }
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); }
public void SetActiveResource(IffChunk chunk, GameIffResource res) { ActiveString = (STR)chunk; UpdateStrings(); }
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; }
public ResAction(UIResActionDelegate action, IffChunk chunk) : this(action, chunk, true, null) { }
public ResAction(UIResActionDelegate action, IffChunk chunk, bool causesChange) : this(action, chunk, causesChange, null) { }
/// <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); } } } } }
public void GotoResource(IffChunk chunk) { GotoResource(chunk.GetType(), chunk.ChunkID); }
public void ChunkChanged(IffChunk chunk) { chunk.RuntimeInfo = ChunkRuntimeState.Modified; chunk.ChunkParent.RuntimeInfo.Dirty = true; IffChanged(chunk.ChunkParent); }
public void SetActiveResource(IffChunk chunk, GameIffResource res) { ActiveRes = chunk; }
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); }
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; }
public void SetActiveResource(IffChunk chunk, GameIffResource res) { ActiveChunk = (BHAV)chunk; ActiveMeta = res.Get<TPRP>(chunk.ChunkID); RefreshDisplay(); }