public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen) { if ((header->Algorithm != CompressionType.LZ77) || (header->Parameter != 0)) { throw new InvalidCompressionException("Compression header does not match LZ77 format."); } for (byte *srcPtr = (byte *)header->Data, dstPtr = (byte *)dstAddress, ceiling = dstPtr + dstLen; dstPtr < ceiling;) { for (byte control = *srcPtr++, bit = 8; (bit-- != 0) && (dstPtr != ceiling);) { if ((control & (1 << bit)) == 0) { *dstPtr++ = *srcPtr++; } else { for (int num = (*srcPtr >> 4) + 3, offset = (((*srcPtr++ & 0xF) << 8) | *srcPtr++) + 2; (dstPtr != ceiling) && (num-- > 0); *dstPtr++ = dstPtr[-offset]) { ; } } } } }
public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen) { uint total = 0; VoidPtr ceil = dstAddress + dstLen; if (header->Parameter != 1) { byte *pSrc = (byte *)header->Data; byte *pDst = (byte *)dstAddress; do { total += *pSrc++; *pDst++ = (byte)total; }while (pSrc < (byte *)ceil); } else { bushort *pSrc = (bushort *)header->Data; bushort *pDst = (bushort *)dstAddress; do { total += *pSrc++; *pDst++ = (ushort)total; }while ((byte *)pSrc < (byte *)ceil); } }
public static CompressionType GetAlgorithm(VoidPtr addr, int length) { BinTag compTag = *(BinTag *)addr; if (compTag == YAZ0.Tag) { return(CompressionType.RunLengthYAZ0); } else if (compTag == YAY0.Tag) { return(CompressionType.RunLengthYAY0); } else { CompressionHeader *cmpr = (CompressionHeader *)addr; if (cmpr->ExpandedSize < length) { return(CompressionType.None); } if (!cmpr->HasLegitCompression()) { return(CompressionType.None); } //Check to make sure we're not reading a tag if (IsTag((byte *)addr)) { return(CompressionType.None); } return(cmpr->Algorithm); } }
public static unsafe ResourceNode FromSource(ResourceNode parent, DataSource source) { ResourceNode n = null; if ((n = GetRaw(source)) != null) { n.Initialize(parent, source); } else { //Check for compression? if (Compressor.IsDataCompressed(source.Address, source.Length)) { if ((*(uint *)source.Address) == YAZ0.Tag) { YAZ0 *cmpr = (YAZ0 *)source.Address; try { //Expand the whole resource and initialize FileMap map = FileMap.FromTempFile((int)cmpr->_unCompDataLen); Compressor.Expand(cmpr, map.Address, map.Length); source.Compression = CompressionType.RunLength; //Check for a match if ((n = GetRaw(new DataSource(map.Address, map.Length))) != null) { n.Initialize(parent, source, new DataSource(map)); } } catch (InvalidCompressionException e) { MessageBox.Show(e.ToString()); } } else { CompressionHeader *cmpr = (CompressionHeader *)source.Address; if (Compressor.Supports(cmpr->Algorithm)) { try { //Expand a portion of the data byte *buffer = stackalloc byte[CompressBufferLen]; Compressor.Expand(cmpr, buffer, CompressBufferLen); //Check for a match if ((n = GetRaw(new DataSource(buffer, CompressBufferLen))) != null) { //Expand the whole resource and initialize FileMap map = FileMap.FromTempFile(cmpr->ExpandedSize); Compressor.Expand(cmpr, map.Address, map.Length); source.Compression = cmpr->Algorithm; n.Initialize(parent, source, new DataSource(map)); } } catch (InvalidCompressionException e) { MessageBox.Show(e.ToString()); } } } } } return(n); }
public static void Expand(CompressionHeader *header, VoidPtr dstAddr, int dstLen) { switch (header->Algorithm) { case CompressionType.LZ77: { LZ77.Expand(header, dstAddr, dstLen); break; } case CompressionType.Huffman: case CompressionType.RunLength: case CompressionType.Differential: default: throw new InvalidCompressionException("Unknown compression type."); } }
public unsafe virtual void ReplaceRaw(FileMap map) { if (_children != null) { foreach (ResourceNode node in _children) { node.Dispose(); } _children.Clear(); _children = null; } _replUncompSrc.Close(); _replSrc.Close(); if (Compressor.IsDataCompressed(map.Address, map.Length)) { CompressionHeader *cmpr = (CompressionHeader *)map.Address; _compression = cmpr->Algorithm; if (Compressor.Supports(cmpr->Algorithm)) { FileMap uncompMap = FileMap.FromTempFile(cmpr->ExpandedSize); Compressor.Expand(cmpr, uncompMap.Address, uncompMap.Length); _replSrc = new DataSource(map, cmpr->Algorithm); _replUncompSrc = new DataSource(uncompMap); } else { _replSrc = _replUncompSrc = new DataSource(map); } } else { _compression = CompressionType.None; _replSrc = _replUncompSrc = new DataSource(map); } _replaced = true; if (!OnInitialize()) { _children = new List <ResourceNode>(); } _replaced = false; _changed = false; if (Replaced != null) { Replaced(this); } }
public static bool IsDataCompressed(VoidPtr addr, int length) { CompressionHeader *cmpr = (CompressionHeader *)addr; if (cmpr->ExpandedSize < length) { return(false); } switch (cmpr->Algorithm) { case CompressionType.LZ77: return(cmpr->Parameter == 0); default: return(false); } }
public static FileMap TryExpand(ref DataSource source, bool doTest = true) { FileMap decompressedMap = null; CompressionType algorithm = GetAlgorithm(source); if (Supports(source.Compression = algorithm)) { try { if (doTest && !Test(algorithm, source.Address)) { return(null); } uint len = 0; if (algorithm == CompressionType.RunLengthYAZ0) { len = *(buint *)(source.Address + 4); decompressedMap = FileMap.FromTempFile((int)len); Expand((YAZ0 *)source.Address, decompressedMap.Address, decompressedMap.Length); } else if (algorithm == CompressionType.RunLengthYAY0) { len = *(buint *)(source.Address + 4); decompressedMap = FileMap.FromTempFile((int)len); Expand((YAY0 *)source.Address, decompressedMap.Address, decompressedMap.Length); } else { CompressionHeader *hdr = (CompressionHeader *)source.Address; len = hdr->ExpandedSize; decompressedMap = FileMap.FromTempFile((int)len); Expand(hdr, decompressedMap.Address, decompressedMap.Length); } } catch (InvalidCompressionException e) { MessageBox.Show(e.ToString()); } } return(decompressedMap); }
public unsafe static int Main(string[] args) { if (args.Length != 3) { Console.Error.WriteLine(USAGE); return(1); } if (!new[] { "banner", "icon", "sound" }.Contains(args[1])) { Console.Error.WriteLine(USAGE); return(1); } string parent_archive = Path.GetTempFileName(); try { using (var fs1 = new FileStream(args[0], FileMode.Open, FileAccess.Read)) using (var fs2 = new FileStream(parent_archive, FileMode.Create, FileAccess.Write)) { fs1.Position = 0x640; fs1.CopyTo(fs2); } using (var parent_node = NodeFactory.FromFile(null, parent_archive)) { var child_node = parent_node.FindChild($"meta/{args[1]}.bin", false); CompressionHeader *header = (CompressionHeader *)(child_node.WorkingSource.Address + 0x24); byte[] buffer = new byte[checked ((int)header->ExpandedSize)]; fixed(byte *ptr = buffer) { LZ77.Expand(header, ptr, buffer.Length); } File.WriteAllBytes(args[2], buffer); } return(0); } finally { if (File.Exists(parent_archive)) { File.Delete(parent_archive); } } }
public static bool IsDataCompressed(VoidPtr addr, int length) { if (*(uint *)addr == YAZ0.Tag) { return(true); } else { CompressionHeader *cmpr = (CompressionHeader *)addr; if (cmpr->ExpandedSize < length) { return(false); } switch (cmpr->Algorithm) { case CompressionType.LZ77: return(true); default: return(false); } } }
public static bool IsDataCompressed(VoidPtr addr, int length) { if (*(uint *)addr == YAZ0.Tag) { return(true); } else { CompressionHeader *cmpr = (CompressionHeader *)addr; if (cmpr->ExpandedSize < length) { return(false); } if (!cmpr->HasLegitCompression()) { return(false); } char[] chars = characters.ToCharArray(); //Check to make sure we're not reading a tag byte * c = (byte *)addr; byte[] tag = { c[0], c[1], c[2], c[3] }; if ((Array.IndexOf(chars, (char)tag[0]) >= 0) && (Array.IndexOf(chars, (char)tag[1]) >= 0) && (Array.IndexOf(chars, (char)tag[2]) >= 0) && (Array.IndexOf(chars, (char)tag[3]) >= 0)) { return(false); } return(true); } }
public static unsafe ResourceNode FromSource(ResourceNode parent, DataSource source) { ResourceNode n = null; if ((n = GetRaw(source)) != null) { n.Initialize(parent, source); } else { //Check for compression? if (Compressor.IsDataCompressed(source.Address, source.Length)) { CompressionHeader *cmpr = (CompressionHeader *)source.Address; try { //Expand a portion of the data byte *buffer = stackalloc byte[CompressBufferLen]; Compressor.Expand(cmpr, buffer, CompressBufferLen); //Check for a match if ((n = GetRaw(new DataSource(buffer, CompressBufferLen))) != null) { //Expand the whole resource and initialize FileMap map = FileMap.FromTempFile(cmpr->ExpandedSize); Compressor.Expand(cmpr, map.Address, map.Length); source.Compression = cmpr->Algorithm; n.Initialize(parent, source, new DataSource(map)); } } catch (InvalidCompressionException) { } } } return(n); }
public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen) { }
public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen) { Expand(header->Data, dstAddress, dstLen, header->IsExtendedLZ77); }
//Parser commands must initialize the node before returning. public unsafe static ResourceNode FromFile(ResourceNode parent, string path) { ResourceNode node = null; FileMap map = FileMap.FromFile(path, FileMapProtect.Read); try { DataSource source = new DataSource(map); if (String.Equals(Path.GetExtension(path), ".mrg", StringComparison.OrdinalIgnoreCase) || String.Equals(Path.GetExtension(path), ".mrgc", StringComparison.OrdinalIgnoreCase)) { node = new MRGNode(); if (Compressor.IsDataCompressed(source.Address, source.Length)) { CompressionHeader *cmpr = (CompressionHeader *)source.Address; source.Compression = cmpr->Algorithm; if (Compressor.Supports(cmpr->Algorithm)) { try { //Expand the whole resource and initialize FileMap uncompMap = FileMap.FromTempFile(cmpr->ExpandedSize); Compressor.Expand(cmpr, uncompMap.Address, uncompMap.Length); node.Initialize(parent, source, new DataSource(uncompMap)); } catch (InvalidCompressionException e) { MessageBox.Show(e.ToString()); } } else { node.Initialize(parent, source); } } else { node.Initialize(parent, source); } } else if (String.Equals(Path.GetExtension(path), ".rel", StringComparison.OrdinalIgnoreCase)) { node = new RELNode(); node.Initialize(parent, map); } else if (String.Equals(Path.GetExtension(path), ".dol", StringComparison.OrdinalIgnoreCase)) { node = new DOLNode(); node.Initialize(parent, map); } else if ((node = FromSource(parent, source)) == null) { //if (Compressor.IsDataCompressed(source.Address, source.Length)) //{ // CompressionHeader* cmpr = (CompressionHeader*)source.Address; // if (!Compressor.Supports(cmpr->Algorithm)) // MessageBox.Show("File uses unsupported " + cmpr->Algorithm.ToString() + " compression."); //} } } finally { if (node == null) { map.Dispose(); } } return(node); }