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(); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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); }
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(); }
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(); }
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(); }
/// <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; }