private byte[] PackedChunk(ResourceIndexEntry ie) { byte[] chunk; if (ie.IsDirty) { Stream res = GetResource(ie); BinaryReader r = new BinaryReader(res); res.Position = 0; chunk = r.ReadBytes((int)ie.Memsize); if (Checking) { if (chunk.Length != (int)ie.Memsize) { throw new OverflowException( $"packedChunk, dirty resource - T: 0x{ie.ResourceType:X}, G: 0x{ie.ResourceGroup:X}, I: 0x{ie.Instance:X}: Length expected: 0x{ie.Memsize:X}, read: 0x{chunk.Length:X}"); } } byte[] comp = ie.Compressed != 0 ? Compression.CompressStream(chunk) : chunk; if (comp.Length < chunk.Length) { chunk = comp; } } else { if (Checking) { if (_packageStream == null) { throw new InvalidOperationException( $"Clean resource with undefined \"current package\" - T: 0x{ie.ResourceType:X}, G: 0x{ie.ResourceGroup:X}, I: 0x{ie.Instance:X}"); } } _packageStream.Position = ie.Chunkoffset; chunk = (new BinaryReader(_packageStream)).ReadBytes((int)ie.Filesize); if (Checking) { if (chunk.Length != (int)ie.Filesize) { throw new OverflowException( $"packedChunk, clean resource - T: 0x{ie.ResourceType:X}, G: 0x{ie.ResourceGroup:X}, I: 0x{ie.Instance:X}: Length expected: 0x{ie.Filesize:X}, read: 0x{chunk.Length:X}"); } } } return(chunk); }
public IResourceIndexEntry Add(IResourceKey rk) { ResourceIndexEntry rc = new ResourceIndexEntry(new int[Hdrsize], new int[NumFields - Hdrsize]) { ResourceType = rk.ResourceType, ResourceGroup = rk.ResourceGroup, Instance = rk.Instance, Chunkoffset = 0xffffffff, Unknown2 = 1, ResourceStream = null }; base.Add(rc); return(rc); }
/// <summary> /// Return the index entry with the matching TGI /// </summary> /// <param name="type">Entry type</param> /// <param name="group">Entry group</param> /// <param name="instance">Entry instance</param> /// <returns>Matching entry</returns> public IResourceIndexEntry this[uint type, uint group, ulong instance] { get { for (int index = 0; index < Count; index++) { ResourceIndexEntry rie = (ResourceIndexEntry)this[index]; if (rie.ResourceType != type) { continue; } if (rie.ResourceGroup != @group) { continue; } if (rie.Instance == instance) { return(rie); } } return(null); } }
/// <summary> /// Save the package to a given stream /// </summary> /// <param name="s">Stream to save to</param> public override void SaveAs(Stream s) { BinaryWriter w = new BinaryWriter(s); w.Write(_header); List <uint> lT = new List <uint>(); List <uint> lG = new List <uint>(); List <uint> lIh = new List <uint>(); for (int i = 0; i < Index.Count; i++) { IResourceIndexEntry x = Index[i]; if (!lT.Contains(x.ResourceType)) { lT.Add(x.ResourceType); } if (!lG.Contains(x.ResourceGroup)) { lG.Add(x.ResourceGroup); } if (!lIh.Contains((uint)(x.Instance >> 32))) { lIh.Add((uint)(x.Instance >> 32)); } } uint indexType = (uint)(lIh.Count <= 1 ? 0x04 : 0x00) | (uint)(lG.Count <= 1 ? 0x02 : 0x00) | (uint)(lT.Count <= 1 ? 0x01 : 0x00); PackageIndex newIndex = new PackageIndex(indexType); for (int i = 0; i < Index.Count; i++) { IResourceIndexEntry ie = Index[i]; if (ie.IsDeleted) { continue; } ResourceIndexEntry newIe = (ie as ResourceIndexEntry)?.Clone(); ((List <IResourceIndexEntry>)newIndex).Add(newIe); byte[] value = PackedChunk(ie as ResourceIndexEntry); newIe.Chunkoffset = (uint)s.Position; w.Write(value); w.Flush(); if (value.Length < newIe.Memsize) { newIe.Compressed = 0xffff; newIe.Filesize = (uint)value.Length; } else { newIe.Compressed = 0x0000; newIe.Filesize = newIe.Memsize; } } long indexpos = s.Position; newIndex.Save(w); SetIndexcount(w, newIndex.Count); SetIndexsize(w, newIndex.Size); SetIndexposition(w, (int)indexpos); s.Flush(); }