예제 #1
0
        public static void WriteNgKeys(string fileName, byte[][] keys)
        {
            var fs = new FileStream(fileName, FileMode.Create);
            var wr = new DataWriter(fs);

            for (int i = 0; i < 101; i++)
            {
                wr.Write(keys[i]);
            }

            fs.Close();
        }
예제 #2
0
        /// <summary>
        /// Writes the resource file entry.
        /// </summary>
        public void Write(DataWriter writer)
        {
            writer.Write((ushort)NameOffset);

            var buf1 = new byte[] {
                (byte)((FileSize >> 0) & 0xFF),
                (byte)((FileSize >> 8) & 0xFF),
                (byte)((FileSize >> 16) & 0xFF)
            };
            writer.Write(buf1);

            var buf2 = new byte[] {
                (byte)((FileOffset >> 0) & 0xFF),
                (byte)((FileOffset >> 8) & 0xFF),
                (byte)(((FileOffset >> 16) & 0xFF) | 0x80)
            };
            writer.Write(buf2);

            writer.Write(SystemFlags);
            writer.Write(GraphicsFlags);
        }
예제 #3
0
        /// <summary>
        /// Writes the binary file entry.
        /// </summary>
        public void Write(DataWriter writer)
        {
            writer.Write((ushort)NameOffset);

            var buf1 = new byte[] {
                (byte)((FileSize >> 0) & 0xFF),
                (byte)((FileSize >> 8) & 0xFF),
                (byte)((FileSize >> 16) & 0xFF)
            };
            writer.Write(buf1);

            var buf2 = new byte[] {
                (byte)((FileOffset >> 0) & 0xFF),
                (byte)((FileOffset >> 8) & 0xFF),
                (byte)((FileOffset >> 16) & 0xFF)
            };
            writer.Write(buf2);

            writer.Write(FileUncompressedSize);

            if (IsEncrypted)
                writer.Write((uint)1);
            else
                writer.Write((uint)0);
        }
예제 #4
0
 /// <summary>
 /// Writes the directory entry.
 /// </summary>
 public void Write(DataWriter writer)
 {
     writer.Write(this.NameOffset);
     writer.Write((uint)0x7FFFFF00);
     writer.Write(this.EntriesIndex);
     writer.Write(this.EntriesCount);
 }
예제 #5
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            // backup position
            var positionBackup = BaseStream.Position;

            var writer = new DataWriter(BaseStream);


            var entries = new List<IRageArchiveEntry7>();
            var stack = new Stack<RageArchiveDirectory7>();
            var nameOffset = 1;


            entries.Add(Root);
            stack.Push(Root);

            var nameDict = new Dictionary<string, uint>();
            nameDict.Add("", 0);

            while (stack.Count > 0)
            {
                var directory = stack.Pop();

                directory.EntriesIndex = (uint)entries.Count;
                directory.EntriesCount = (uint)directory.Directories.Count + (uint)directory.Files.Count;

                var theList = new List<IRageArchiveEntry7>();

                foreach (var xd in directory.Directories)
                {
                    if (!nameDict.ContainsKey(xd.Name))
                    {
                        nameDict.Add(xd.Name, (uint)nameOffset);
                        nameOffset += xd.Name.Length + 1;
                    }
                    xd.NameOffset = nameDict[xd.Name];

                    //xd.NameOffset = (ushort)nameOffset;
                    //nameOffset += xd.Name.Length + 1;
                    //entries.Add(xd);
                    //stack.Push(xd);
                    theList.Add(xd);
                }

                foreach (var xf in directory.Files)
                {
                    if (!nameDict.ContainsKey(xf.Name))
                    {
                        nameDict.Add(xf.Name, (uint)nameOffset);
                        nameOffset += xf.Name.Length + 1;
                    }
                    xf.NameOffset = nameDict[xf.Name];

                    //xf.NameOffset = (ushort)nameOffset;
                    //nameOffset += xf.Name.Length + 1;
                    //entries.Add(xf);
                    theList.Add(xf);
                }

                theList.Sort(
                    delegate (IRageArchiveEntry7 a, IRageArchiveEntry7 b)
                    {
                        return string.CompareOrdinal(a.Name, b.Name);
                    }
                    );
                foreach (var xx in theList)
                    entries.Add(xx);
                theList.Reverse();
                foreach (var xx in theList)
                    if (xx is RageArchiveDirectory7)
                        stack.Push((RageArchiveDirectory7)xx);
            }


            // there are sometimes resources with length>=0xffffff which actually
            // means length=0xffffff
            // -> we therefore just cut the file size
            foreach (var entry in entries)
                if (entry is RageArchiveResourceFile7)
                {
                    var resource = entry as RageArchiveResourceFile7;
                    if (resource.FileSize > 0xFFFFFF)
                    {
                        var buf = new byte[16];
                        buf[7] = (byte)((resource.FileSize >> 0) & 0xFF);
                        buf[14] = (byte)((resource.FileSize >> 8) & 0xFF);
                        buf[5] = (byte)((resource.FileSize >> 16) & 0xFF);
                        buf[2] = (byte)((resource.FileSize >> 24) & 0xFF);

                        if (writer.Length > 512 * resource.FileOffset)
                        {
                            writer.Position = 512 * resource.FileOffset;
                            writer.Write(buf);
                        }                     

                        resource.FileSize = 0xFFFFFF;
                    }                        
                }


            // entries...
            var ent_str = new MemoryStream();
            var ent_wr = new DataWriter(ent_str);
            foreach (var entry in entries)
                entry.Write(ent_wr);
            ent_str.Flush();

            var ent_buf = new byte[ent_str.Length];
            ent_str.Position = 0;
            ent_str.Read(ent_buf, 0, ent_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
                ent_buf = AesEncryption.EncryptData(ent_buf, aesKey);
            if (Encryption == RageArchiveEncryption7.NG)
                ent_buf = GTA5Crypto.Encrypt(ent_buf, ngKey);


            // names...
            var n_str = new MemoryStream();
            var n_wr = new DataWriter(n_str);
            //foreach (var entry in entries)
            //    n_wr.Write(entry.Name);
            foreach (var entry in nameDict)
                n_wr.Write(entry.Key);
            var empty = new byte[16 - (n_wr.Length % 16)];
            n_wr.Write(empty);
            n_str.Flush();

            var n_buf = new byte[n_str.Length];
            n_str.Position = 0;
            n_str.Read(n_buf, 0, n_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
                n_buf = AesEncryption.EncryptData(n_buf, aesKey);
            if (Encryption == RageArchiveEncryption7.NG)
                n_buf = GTA5Crypto.Encrypt(n_buf, ngKey);



            writer.Position = 0;
            writer.Write((uint)IDENT);
            writer.Write((uint)entries.Count);
            writer.Write((uint)n_buf.Length);

            switch (Encryption)
            {
                case RageArchiveEncryption7.None:
                    writer.Write((uint)0x04E45504F);
                    break;
                case RageArchiveEncryption7.AES:
                    writer.Write((uint)0x0ffffff9);
                    break;
                case RageArchiveEncryption7.NG:
                    writer.Write((uint)0x0fefffff);
                    break;
            }

            writer.Write(ent_buf);
            writer.Write(n_buf);



            // restore position
            BaseStream.Position = positionBackup;
        }
예제 #6
0
        /// <summary>
        /// Exports a resource file.
        /// </summary>
        public void Export(Stream stream)
        {
            // find version
            // -> http://dageron.com/?page_id=5446&lang=en
            var version = ((file.GraphicsFlags & 0xF0000000) >> 28) |
                          ((file.SystemFlags & 0xF0000000) >> 24);

            var writer = new DataWriter(stream);
            writer.Write((uint)0x07435352);
            writer.Write((uint)version);
            writer.Write((uint)file.SystemFlags);
            writer.Write((uint)file.GraphicsFlags);

            var resourceStream = new PartialStream(
                   archiveWrapper.archive_.BaseStream,
                   delegate () // offset
                   {
                       return file.FileOffset * RageArchiveWrapper7.BLOCK_SIZE;
                   },
                   delegate () // size
                   {
                       return file.FileSize;
                   }
               );
            var resourceReader = new DataReader(resourceStream);

            resourceReader.Position = 16;
            var buf = resourceReader.ReadBytes((int)resourceReader.Length - 16);
            writer.Write(buf);
        }
예제 #7
0
        public virtual void Save(Stream stream)
        {
            var writer = new DataWriter(stream);

            uint systemFlags = 0;
            systemFlags |= (uint)((Version >> 4) & 0x0F) << 28;
            systemFlags |= (uint)SystemPagesDiv16 << 27;
            systemFlags |= (uint)SystemPagesDiv8 << 26;
            systemFlags |= (uint)SystemPagesDiv4 << 25;
            systemFlags |= (uint)SystemPagesDiv2 << 24;
            systemFlags |= (uint)SystemPagesMul1 << 17;
            systemFlags |= (uint)SystemPagesMul2 << 11;
            systemFlags |= (uint)SystemPagesMul4 << 7;
            systemFlags |= (uint)SystemPagesMul8 << 5;
            systemFlags |= (uint)SystemPagesMul16 << 4;
            systemFlags |= (uint)SystemPagesSizeShift;

            uint graphicsFlags = 0;
            graphicsFlags |= (uint)((Version >> 0) & 0x0F) << 28;
            graphicsFlags |= (uint)GraphicsPagesDiv16 << 27;
            graphicsFlags |= (uint)GraphicsPagesDiv8 << 26;
            graphicsFlags |= (uint)GraphicsPagesDiv4 << 25;
            graphicsFlags |= (uint)GraphicsPagesDiv2 << 24;
            graphicsFlags |= (uint)GraphicsPagesMul1 << 17;
            graphicsFlags |= (uint)GraphicsPagesMul2 << 11;
            graphicsFlags |= (uint)GraphicsPagesMul4 << 7;
            graphicsFlags |= (uint)GraphicsPagesMul8 << 5;
            graphicsFlags |= (uint)GraphicsPagesMul16 << 4;
            graphicsFlags |= (uint)GraphicsPagesSizeShift;

            writer.Write((uint)0x37435352);
            writer.Write((int)Version);
            writer.Write((uint)systemFlags);
            writer.Write((uint)graphicsFlags);

            var deflateStream = new DeflateStream(stream, CompressionMode.Compress, true);
            deflateStream.Write(SystemData, 0, SystemData.Length);
            deflateStream.Write(GraphicsData, 0, GraphicsData.Length);
            deflateStream.Flush();
            deflateStream.Close();
        }
예제 #8
0
        public static void WriteNgTables(string fileName, uint[][][] tableData)
        {
            var fs = new FileStream(fileName, FileMode.Create);
            var wr = new DataWriter(fs);

            // 17 rounds...
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                for (int j = 0; j < 16; j++)
                {
                    // 256 entries...
                    for (int k = 0; k < 256; k++)
                    {
                        wr.Write(tableData[i][j][k]);
                    }
                }
            }

            fs.Close();
        }
예제 #9
0
        public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData)
        {
            var fs = new FileStream(fileName, FileMode.Create);
            var wr = new DataWriter(fs);

            // 17 rounds...
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                for (int j = 0; j < 16; j++)
                {
                    GTA5NGLUT lut = lutData[i][j];

                    // first compression step (2^32 -> 2^24)
                    for (int k = 0; k < 256; k++)
                        for (int l = 0; l < 256; l++)
                            wr.Write(lut.LUT0[k][l]);

                    // second compression step (2^24 -> 2^16)
                    for (int k = 0; k < 256; k++)
                        for (int l = 0; l < 256; l++)
                            wr.Write(lut.LUT1[k][l]);

                    // indices
                    for (int k = 0; k < 65536; k++)
                        wr.Write(lut.Indices[k]);
                }
            }

            fs.Close();
        }
예제 #10
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            // backup position
            var positionBackup = BaseStream.Position;

            var writer = new DataWriter(BaseStream);

            var entries = new List<IRageArchiveEntry7>();
            var stack = new Stack<RageArchiveDirectory7>();
            var nameOffset = 1;

            entries.Add(Root);
            stack.Push(Root);

            var nameDict = new Dictionary<string, uint>();
            nameDict.Add("", 0);

            while (stack.Count > 0)
            {
                var directory = stack.Pop();

                directory.EntriesIndex = (uint)entries.Count;
                directory.EntriesCount = (uint)directory.Directories.Count + (uint)directory.Files.Count;

                var theList = new List<IRageArchiveEntry7>();

                foreach (var xd in directory.Directories)
                {
                    if (!nameDict.ContainsKey(xd.Name))
                    {
                        nameDict.Add(xd.Name, (uint)nameOffset);
                        nameOffset += xd.Name.Length + 1;
                    }
                    xd.NameOffset = nameDict[xd.Name];

                    //xd.NameOffset = (ushort)nameOffset;
                    //nameOffset += xd.Name.Length + 1;
                    //entries.Add(xd);
                    //stack.Push(xd);
                    theList.Add(xd);
                }

                foreach (var xf in directory.Files)
                {
                    if (!nameDict.ContainsKey(xf.Name))
                    {
                        nameDict.Add(xf.Name, (uint)nameOffset);
                        nameOffset += xf.Name.Length + 1;
                    }
                    xf.NameOffset = nameDict[xf.Name];

                    //xf.NameOffset = (ushort)nameOffset;
                    //nameOffset += xf.Name.Length + 1;
                    //entries.Add(xf);
                    theList.Add(xf);
                }

                theList.Sort(
                    delegate (IRageArchiveEntry7 a, IRageArchiveEntry7 b)
                    {
                        return string.CompareOrdinal(a.Name, b.Name);
                    }
                    );
                foreach (var xx in theList)
                    entries.Add(xx);
                theList.Reverse();
                foreach (var xx in theList)
                    if (xx is RageArchiveDirectory7)
                        stack.Push((RageArchiveDirectory7)xx);
            }

            // entries...
            var ent_str = new MemoryStream();
            var ent_wr = new DataWriter(ent_str);
            foreach (var entry in entries)
                entry.Write(ent_wr);
            ent_str.Flush();

            var ent_buf = new byte[ent_str.Length];
            ent_str.Position = 0;
            ent_str.Read(ent_buf, 0, ent_buf.Length);

            if (IsAesEncrypted && aesKey != null)
                ent_buf = AesEncryption.EncryptData(ent_buf, aesKey);
            else if (!IsAesEncrypted && ngKey != null)
                ent_buf = GTA5Crypto.Encrypt(ent_buf, ngKey);

            // names...
            var n_str = new MemoryStream();
            var n_wr = new DataWriter(n_str);
            //foreach (var entry in entries)
            //    n_wr.Write(entry.Name);
            foreach (var entry in nameDict)
                n_wr.Write(entry.Key);
            var empty = new byte[16 - (n_wr.Length % 16)];
            n_wr.Write(empty);
            n_str.Flush();

            var n_buf = new byte[n_str.Length];
            n_str.Position = 0;
            n_str.Read(n_buf, 0, n_buf.Length);

            if (IsAesEncrypted && aesKey != null)
                n_buf = AesEncryption.EncryptData(n_buf, aesKey);
            else if (!IsAesEncrypted && ngKey != null)
                n_buf = GTA5Crypto.Encrypt(n_buf, ngKey);

            writer.Position = 0;
            writer.Write((uint)IDENT);
            writer.Write((uint)entries.Count);
            writer.Write((uint)n_buf.Length);

            if (IsAesEncrypted && aesKey != null)
                writer.Write((uint)0x0ffffff9);
            else if (!IsAesEncrypted && ngKey != null)
                writer.Write((uint)0x0fefffff);
            else
                writer.Write((uint)0x04E45504F); // for OpenIV compatibility

            writer.Write(ent_buf);
            writer.Write(n_buf);

            // restore position
            BaseStream.Position = positionBackup;
        }