예제 #1
0
        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])
                        {
                            ;
                        }
                    }
                }
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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.");
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
                }
            }
        }
예제 #10
0
        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);
                }
            }
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
 public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen)
 {
 }
예제 #14
0
 public static void Expand(CompressionHeader *header, VoidPtr dstAddress, int dstLen)
 {
     Expand(header->Data, dstAddress, dstLen, header->IsExtendedLZ77);
 }
예제 #15
0
        //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);
        }