Esempio n. 1
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            var reader = new DataReader(BaseStream);
            var posbak = reader.Position;
            reader.Position = 0;

            uint header_identifier = reader.ReadUInt32(); // 0x52504637
            if (header_identifier != IDENT)
                throw new Exception("The identifier " + header_identifier.ToString("X8") + " did not match the expected value of 0x52504637");

            uint header_entriesCount = reader.ReadUInt32();
            uint header_namesLength = reader.ReadUInt32();
            uint header_encryption = reader.ReadUInt32();

            byte[] entries_data_dec = null;
            byte[] names_data_dec = null;

            if (header_encryption == 0x04E45504F) // for OpenIV compatibility
            {
                // no encryption...
                Encryption = RageArchiveEncryption7.None;
                entries_data_dec = reader.ReadBytes(16 * (int)header_entriesCount);
                names_data_dec = reader.ReadBytes((int)header_namesLength);

            }
            else if (header_encryption == 0x0ffffff9)
            {
                // AES enceyption...                

                Encryption = RageArchiveEncryption7.AES;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = AesEncryption.DecryptData(entries_data, aesKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = AesEncryption.DecryptData(names_data, aesKey);
            }
            else
            {
                // NG encryption...

                Encryption = RageArchiveEncryption7.NG;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = GTA5Crypto.Decrypt(entries_data, ngKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = GTA5Crypto.Decrypt(names_data, ngKey);
            }

            var entries_reader = new DataReader(new MemoryStream(entries_data_dec));
            var names_reader = new DataReader(new MemoryStream(names_data_dec));

            var entries = new List<IRageArchiveEntry7>();
            for (var index = 0; index < header_entriesCount; index++)
            {
                entries_reader.Position += 4;
                int x = entries_reader.ReadInt32();
                entries_reader.Position -= 8;

                if (x == 0x7fffff00)
                {
                    // directory
                    var e = new RageArchiveDirectory7();
                    e.Read(entries_reader);

                    names_reader.Position = e.NameOffset;
                    e.Name = names_reader.ReadString();

                    entries.Add(e);
                }
                else
                {
                    if ((x & 0x80000000) == 0)
                    {
                        // binary file
                        var e = new RageArchiveBinaryFile7();
                        e.Read(entries_reader);

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                    else
                    {
                        // resource file
                        var e = new RageArchiveResourceFile7();
                        e.Read(entries_reader);

                        // there are sometimes resources with length=0xffffff which actually
                        // means length>=0xffffff
                        if (e.FileSize == 0xFFFFFF)
                        {
                            reader.Position = 512 * e.FileOffset;
                            var buf = reader.ReadBytes(16);
                            e.FileSize = ((uint)buf[7] << 0) | ((uint)buf[14] << 8) | ((uint)buf[5] << 16) | ((uint)buf[2] << 24);
                        }

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();
                        
                        entries.Add(e);
                    }
                }
            }

            var stack = new Stack<RageArchiveDirectory7>();
            stack.Push((RageArchiveDirectory7)entries[0]);
            Root = (RageArchiveDirectory7)entries[0];
            while (stack.Count > 0)
            {
                var item = stack.Pop();

                for (int index = (int)item.EntriesIndex; index < (item.EntriesIndex + item.EntriesCount); index++)
                {
                    if (entries[index] is RageArchiveDirectory7)
                    {
                        item.Directories.Add(entries[index] as RageArchiveDirectory7);
                        stack.Push(entries[index] as RageArchiveDirectory7);
                    }
                    else
                    {
                        item.Files.Add(entries[index]);
                    }
                }
            }

            reader.Position = posbak;
        }
Esempio n. 2
0
        public virtual void Load(Stream stream)
        {
            var reader = new DataReader(stream);
            reader.Position = 0;

            var ident = reader.ReadUInt32();
            Version = reader.ReadInt32();
            var systemFlags = reader.ReadUInt32();
            var graphicsFlags = reader.ReadUInt32();

            SystemPagesDiv16 = (int)(systemFlags >> 27) & 0x1;
            SystemPagesDiv8 = (int)(systemFlags >> 26) & 0x1;
            SystemPagesDiv4 = (int)(systemFlags >> 25) & 0x1;
            SystemPagesDiv2 = (int)(systemFlags >> 24) & 0x1;
            SystemPagesMul1 = (int)(systemFlags >> 17) & 0x7F;
            SystemPagesMul2 = (int)(systemFlags >> 11) & 0x3F;
            SystemPagesMul4 = (int)(systemFlags >> 7) & 0xF;
            SystemPagesMul8 = (int)(systemFlags >> 5) & 0x3;
            SystemPagesMul16 = (int)(systemFlags >> 4) & 0x1;
            SystemPagesSizeShift = (int)(systemFlags >> 0) & 0xF;
            var systemBaseSize = BASE_SIZE << SystemPagesSizeShift;
            var systemSize =
                systemBaseSize * SystemPagesDiv16 / 16 +
                systemBaseSize * SystemPagesDiv8 / 8 +
                systemBaseSize * SystemPagesDiv4 / 4 +
                systemBaseSize * SystemPagesDiv2 / 2 +
                systemBaseSize * SystemPagesMul1 * 1 +
                systemBaseSize * SystemPagesMul2 * 2 +
                systemBaseSize * SystemPagesMul4 * 4 +
                systemBaseSize * SystemPagesMul8 * 8 +
                systemBaseSize * SystemPagesMul16 * 16;

            GraphicsPagesDiv16 = (int)(graphicsFlags >> 27) & 0x1;
            GraphicsPagesDiv8 = (int)(graphicsFlags >> 26) & 0x1;
            GraphicsPagesDiv4 = (int)(graphicsFlags >> 25) & 0x1;
            GraphicsPagesDiv2 = (int)(graphicsFlags >> 24) & 0x1;
            GraphicsPagesMul1 = (int)(graphicsFlags >> 17) & 0x7F;
            GraphicsPagesMul2 = (int)(graphicsFlags >> 11) & 0x3F;
            GraphicsPagesMul4 = (int)(graphicsFlags >> 7) & 0xF;
            GraphicsPagesMul8 = (int)(graphicsFlags >> 5) & 0x3;
            GraphicsPagesMul16 = (int)(graphicsFlags >> 4) & 0x1;
            GraphicsPagesSizeShift = (int)(graphicsFlags >> 0) & 0xF;
            var graphicsBaseSize = BASE_SIZE << GraphicsPagesSizeShift;
            var graphicsSize =
                graphicsBaseSize * GraphicsPagesDiv16 / 16 +
                graphicsBaseSize * GraphicsPagesDiv8 / 8 +
                graphicsBaseSize * GraphicsPagesDiv4 / 4 +
                graphicsBaseSize * GraphicsPagesDiv2 / 2 +
                graphicsBaseSize * GraphicsPagesMul1 * 1 +
                graphicsBaseSize * GraphicsPagesMul2 * 2 +
                graphicsBaseSize * GraphicsPagesMul4 * 4 +
                graphicsBaseSize * GraphicsPagesMul8 * 8 +
                graphicsBaseSize * GraphicsPagesMul16 * 16;

            SystemData = new byte[systemSize];
            GraphicsData = new byte[graphicsSize];

            var deflateStream = new DeflateStream(stream, CompressionMode.Decompress, true);
            deflateStream.Read(SystemData, 0, systemSize);
            deflateStream.Read(GraphicsData, 0, graphicsSize);
            deflateStream.Close();
        }