public static void Compress(string source, string destination) { RPX rpx = new RPX(source); int shSize = rpx.Header.e_shnum * 0x2C; // 0x2C = rpx.Header.e_shentsize + 4 bytes of CRC32 int sectionsOffset = GetPhysicalSectionSize(shSize) + 0x40; List <KeyValuePair <int, Elf32_Shdr> > shList = new List <KeyValuePair <int, Elf32_Shdr> >(); List <KeyValuePair <int, Elf32_Shdr> > shNew = new List <KeyValuePair <int, Elf32_Shdr> >(); for (int i = 0; i < rpx.SectionHeader.Length; i++) { shList.Add(new KeyValuePair <int, Elf32_Shdr>(i, rpx.SectionHeader[i])); } shList.Sort((pair1, pair2) => Elf32_Shdr.CompareByOffset(pair1.Value, pair2.Value)); FileStream src = File.Open(source, FileMode.Open); FileStream dest = File.Open(destination, FileMode.Create); byte[] srcBytes = new byte[sectionsOffset]; src.Read(srcBytes, 0, srcBytes.Length); dest.Write(srcBytes, 0, srcBytes.Length); for (int i = 0; i < shList.Count; i++) { int key = shList[i].Key; Elf32_Shdr shdr = new Elf32_Shdr(shList[i].Value); if (shList[i].Value.sh_offset >= sectionsOffset) { int padding = 0; if ((shList[i].Value.sh_type & (uint)SHT_RPL.FILEINFO) == (uint)SHT_RPL.FILEINFO || (shList[i].Value.sh_flags & (uint)SHF_RPL.ZLIB) == (uint)SHF_RPL.ZLIB) { shdr.sh_offset = (uint)dest.Position; srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); if ((shList[i].Value.sh_type & (uint)SHT_RPL.FILEINFO) == (uint)SHT_RPL.FILEINFO) { rpx.CRC[shList[i].Key] = Security.ComputeCRC32(srcBytes, 0, srcBytes.Length); } padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } else { shdr.sh_offset = (uint)dest.Position; srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); byte[] compressBytes = Compress(srcBytes); rpx.CRC[shList[i].Key] = Security.ComputeCRC32(srcBytes, 0, srcBytes.Length); if (compressBytes.Length < srcBytes.Length) { shdr.sh_flags |= (uint)SHF_RPL.ZLIB; shdr.sh_size = (uint)compressBytes.Length; padding = GetPhysicalSectionSize(compressBytes.Length) - compressBytes.Length; dest.Write(compressBytes, 0, compressBytes.Length); } else { padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } } byte[] paddingBytes = new byte[padding]; dest.Write(paddingBytes, 0, paddingBytes.Length); } shNew.Add(new KeyValuePair <int, Elf32_Shdr>(key, shdr)); } src.Close(); dest.Position = 0x40; shNew.Sort((pair1, pair2) => pair1.Key.CompareTo(pair2.Key)); for (int i = 0; i < shNew.Count; i++) { dest.Write(shNew[i].Value.ToArray(rpx.Header.e_ident[(byte)EI.DataEncoding]), 0, 0x28); } for (int i = 0; i < rpx.CRC.Length; i++) { dest.WriteByte((byte)(rpx.CRC[i] >> 24)); dest.WriteByte((byte)((rpx.CRC[i] >> 16) & 0xFF)); dest.WriteByte((byte)((rpx.CRC[i] >> 8) & 0xFF)); dest.WriteByte((byte)(rpx.CRC[i] & 0xFF)); } dest.Close(); }
protected void Edit(string rom, string destination, byte speed, byte players, byte soundVolume, byte romType, short widthTv, short widthDrc, short heightTv, short heightDrc) { FileStream fs = File.Open(FileName, FileMode.Open); byte[] rodata = new byte[SectionHeader[RodataSectionIndex].sh_size]; fs.Position = SectionHeader[RodataSectionIndex].sh_offset; fs.Read(rodata, 0, rodata.Length); byte[] textSection = new byte[SectionHeader[TextSectionIndex].sh_size]; fs.Position = SectionHeader[TextSectionIndex].sh_offset; fs.Read(textSection, 0, textSection.Length); fs.Close(); if (rom != null) { if ((SectionHeader[RodataSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { rodata = Decompress(rodata); } rodata = GetNewRodata(CRCsSum, rodata, rom, speed, players, soundVolume, romType); CRC[RodataSectionIndex] = Cll.Security.ComputeCRC32(rodata, 0, rodata.Length); if ((SectionHeader[RodataSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { rodata = Compress(rodata); } } if ((SectionHeader[TextSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { textSection = Decompress(textSection); } int aspectRatioOffset = GetAspectRatioOffset(CRCsSum); if (aspectRatioOffset != 0) { textSection[aspectRatioOffset] = (byte)(heightTv >> 8); textSection[aspectRatioOffset + 0x01] = (byte)(heightTv & 0xFF); textSection[aspectRatioOffset + 0x04] = (byte)(widthTv >> 8); textSection[aspectRatioOffset + 0x05] = (byte)(widthTv & 0xFF); textSection[aspectRatioOffset + 0x30] = (byte)(heightDrc >> 8); textSection[aspectRatioOffset + 0x31] = (byte)(heightDrc & 0xFF); textSection[aspectRatioOffset + 0x34] = (byte)(widthDrc >> 8); textSection[aspectRatioOffset + 0x35] = (byte)(widthDrc & 0xFF); } CRC[TextSectionIndex] = Cll.Security.ComputeCRC32(textSection, 0, textSection.Length); if ((SectionHeader[TextSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { textSection = Compress(textSection); } int shSize = Header.e_shnum * 0x2C; // 0x2C = Header.e_shentsize + 4 bytes of CRC32 int sectionsOffset = GetPhysicalSectionSize(shSize) + 0x40; List <KeyValuePair <int, Elf32_Shdr> > shList = new List <KeyValuePair <int, Elf32_Shdr> >(); List <KeyValuePair <int, Elf32_Shdr> > shNew = new List <KeyValuePair <int, Elf32_Shdr> >(); for (int i = 0; i < SectionHeader.Length; i++) { shList.Add(new KeyValuePair <int, Elf32_Shdr>(i, SectionHeader[i])); } shList.Sort((pair1, pair2) => Elf32_Shdr.CompareByOffset(pair1.Value, pair2.Value)); FileStream src = File.Open(FileName, FileMode.Open); FileStream dest = File.Open(destination, FileMode.Create); byte[] srcBytes = new byte[sectionsOffset]; src.Read(srcBytes, 0, srcBytes.Length); dest.Write(srcBytes, 0, srcBytes.Length); for (int i = 0; i < shList.Count; i++) { int key = shList[i].Key; Elf32_Shdr shdr = new Elf32_Shdr(shList[i].Value); if (shList[i].Value.sh_offset >= sectionsOffset) { int padding = 0; shdr.sh_offset = (uint)dest.Position; if (shList[i].Value.sh_offset == SectionHeader[TextSectionIndex].sh_offset) { shdr.sh_size = (uint)textSection.Length; padding = GetPhysicalSectionSize(textSection.Length) - textSection.Length; dest.Write(textSection, 0, textSection.Length); } else if (shList[i].Value.sh_offset == SectionHeader[RodataSectionIndex].sh_offset) { shdr.sh_size = (uint)rodata.Length; padding = GetPhysicalSectionSize(rodata.Length) - rodata.Length; dest.Write(rodata, 0, rodata.Length); } else { srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } byte[] paddingBytes = new byte[padding]; dest.Write(paddingBytes, 0, paddingBytes.Length); } shNew.Add(new KeyValuePair <int, Elf32_Shdr>(key, shdr)); } src.Close(); dest.Position = 0x40; shNew.Sort((pair1, pair2) => pair1.Key.CompareTo(pair2.Key)); for (int i = 0; i < shNew.Count; i++) { dest.Write(shNew[i].Value.ToArray(), 0, 0x28); } for (int i = 0; i < CRC.Length; i++) { dest.WriteByte((byte)(CRC[i] >> 24)); dest.WriteByte((byte)((CRC[i] >> 16) & 0xFF)); dest.WriteByte((byte)((CRC[i] >> 8) & 0xFF)); dest.WriteByte((byte)(CRC[i] & 0xFF)); } dest.Close(); }