private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects). } if (MMFile != null) { try { MMFile.Dispose(); } finally { }; } MMFile = null; Index = null; disposedValue = true; } }
/// <summary> /// Apply a patch entry. /// </summary> /// <param name="header">Patch entry header.</param> /// <param name="data">Patch entry data.</param> static void ApplyPatchEntry(PatchHeader header, byte[] data) { var address = (int)header.Address; var index = (int)header.Index; if (header.Command == PatchCommand.NewFile) { var newFile = new MMFile { Addr = address, IsCompressed = false, Data = data, End = address + data.Length, IsStatic = header.Flags.HasFlag(PatchFlags.IsStatic), }; RomUtils.AppendFile(newFile); } else if (header.Command == PatchCommand.ExistingFile) { RomUtils.CheckCompressed(index); var original = RomData.MMFileList[index]; original.Data = VcDiffDecodeManaged(original.Data, data); if (original.Data.Length == 0) { original.Cmp_Addr = -1; original.Cmp_End = -1; } } }
private static Dictionary <ushort, MessageEntry> GetMessageTable() { Dictionary <ushort, MessageEntry> messageTable = new Dictionary <ushort, MessageEntry>(); int fileIndex = RomUtils.GetFileIndexForWriting(MESSAGE_TABLE_ADDRESS); MMFile file = MMFileList[fileIndex]; int baseAddress = MESSAGE_TABLE_ADDRESS - file.Addr; var data = file.Data; while (true) { ushort textId = ReadWriteUtils.Arr_ReadU16(data, baseAddress); if (textId >= 0xFFFD) //This id is still valid, but hard to determine it's size { break; } int address = ReadWriteUtils.Arr_ReadS32(data, baseAddress + 4) & 0xFFFFFF; int addressNext = ReadWriteUtils.Arr_ReadS32(data, baseAddress + 12) & 0xFFFFFF; MessageEntry message = new MessageEntry() { Id = textId, Address = address, Size = addressNext - address }; messageTable.Add(textId, message); baseAddress += 8; } return(messageTable); }
public static void InsertObj(byte[] obj, int replace) { int f = RomUtils.GetFileIndexForWriting(Addresses.ObjTable); int basea = Addresses.ObjTable - RomData.MMFileList[f].Addr; uint replaceaddr = ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, basea + (replace * 8)); int objf = RomData.MMFileList.FindIndex(u => u.Addr == replaceaddr); if (objf == -1) { return; } ; if (obj.Length > (RomData.MMFileList[objf].End - RomData.MMFileList[objf].Addr)) { MMFile newfile = new MMFile(); newfile.Addr = RomData.MMFileList[RomData.MMFileList.Count - 1].End; newfile.End = newfile.Addr + obj.Length; newfile.IsCompressed = true; newfile.WasEdited = true; newfile.Data = obj; RomData.MMFileList[objf].Cmp_Addr = -1; RomData.MMFileList[objf].Cmp_End = -1; RomData.MMFileList[objf].Data = null; RomData.MMFileList[objf].IsCompressed = false; RomData.MMFileList.Add(newfile); ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, basea + (replace * 8), (uint)newfile.Addr); ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, basea + (replace * 8) + 4, (uint)newfile.End); } else { RomData.MMFileList[objf].Data = obj; RomData.MMFileList[objf].WasEdited = true; } }
/// <summary> /// Applies the given filename patch to the in-memory RomData /// </summary> /// <param name="filename"></param> /// <returns>SHA256 hash of the patch.</returns> public static byte[] ApplyPatch(string filename) { var hashAlg = new SHA256Managed(); using (var filestream = File.OpenRead(filename)) using (var cryptoStream = new CryptoStream(filestream, hashAlg, CryptoStreamMode.Read)) using (var decompressStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) using (var memoryStream = new MemoryStream()) { decompressStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using (var reader = new BinaryReader(memoryStream)) { var magic = ReadWriteUtils.ReadU32(reader); var version = ReadWriteUtils.ReadU32(reader); // Validate patch magic and version values PatchUtils.Validate(magic, version); while (reader.BaseStream.Position != reader.BaseStream.Length) { var fileIndex = ReadWriteUtils.ReadS32(reader); var fileAddr = ReadWriteUtils.ReadS32(reader); var index = ReadWriteUtils.ReadS32(reader); var isStatic = ReadWriteUtils.ReadS32(reader) != 0 ? true : false; var length = ReadWriteUtils.ReadS32(reader); var data = reader.ReadBytes(length); if (fileIndex >= RomData.MMFileList.Count) { var newFile = new MMFile { Addr = fileAddr, IsCompressed = false, Data = data, End = fileAddr + data.Length, IsStatic = isStatic, }; RomUtils.AppendFile(newFile); } if (index == -1) { RomData.MMFileList[fileIndex].Data = data; if (data.Length == 0) { RomData.MMFileList[fileIndex].Cmp_Addr = -1; RomData.MMFileList[fileIndex].Cmp_End = -1; } } else { CheckCompressed(fileIndex); ReadWriteUtils.Arr_Insert(data, 0, data.Length, RomData.MMFileList[fileIndex].Data, index); } } } return(hashAlg.Hash); } }
public void ReadAsciiString_ReturnsString() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadAsciiString(0x26); Assert.Equal("hello world.", actual); }
public void ReadUnicodeString_ReturnsString() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadUnicodeString(0x34); Assert.Equal("hello", actual); }
public void ReadUShort_ReturnsUShort() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadUShort(0x16); Assert.Equal((ushort)0x2211, actual); }
public void ReadUInt_ReturnsUInt() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadUInt(0x16); Assert.Equal(0x44332211u, actual); }
public void ToArray_ReturnsArray() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ToArray(); Assert.Equal(0x42, actual.Length); }
public void ReadByte_ReturnsByte() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadByte(0x2A); Assert.Equal(0x6F, actual); }
public void ReadULong_ReturnsULong() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var actual = mmf.ReadULong(0x16); Assert.Equal(0x8877665544332211u, actual); }
public void WriteUShort_WritesUShort() { File.Copy(@"Binaries/mmf_test.bin", @"Binaries/mmf_test_writeushort.bin", true); using var mmf = new MMFile(@"Binaries/mmf_test_writeushort.bin"); mmf.WriteUShort(0x15, 0xafbf); Assert.Equal((ushort)0xafbf, mmf.ReadUShort(0x15)); }
public void WriteULong_WritesULong() { File.Copy(@"Binaries/mmf_test.bin", @"Binaries/mmf_test_writeulong.bin", true); using var mmf = new MMFile(@"Binaries/mmf_test_writeulong.bin"); mmf.WriteULong(0x15, 0xafbfcfdfafbfcfdf); Assert.Equal(0xafbfcfdfafbfcfdf, mmf.ReadULong(0x15)); }
public void WriteUInt_WritesUInt() { File.Copy(@"Binaries/mmf_test.bin", @"Binaries/mmf_test_writeuint.bin", true); using var mmf = new MMFile(@"Binaries/mmf_test_writeuint.bin"); mmf.WriteUInt(0x15, 0xafbfcfdf); Assert.Equal(0xafbfcfdfu, mmf.ReadUInt(0x15)); }
public void WriteBytes_WritesBytes() { File.Copy(@"Binaries/mmf_test.bin", @"Binaries/mmf_test_writebytes.bin", true); using var mmf = new MMFile(@"Binaries/mmf_test_writebytes.bin"); mmf.WriteBytes(0x15, new byte[] { 0xaf, 0xbf }); Assert.Equal(0xbfaf, mmf.ReadUShort(0x15)); }
public void WriteByte_WritesByte() { File.Copy(@"Binaries/mmf_test.bin", @"Binaries/mmf_test_writebyte.bin", true); using var mmf = new MMFile(@"Binaries/mmf_test_writebyte.bin"); mmf.WriteByte(0x15, 0xaf); Assert.Equal((byte)0xaf, mmf.ReadByte(0x15)); }
public void AsSpan_ReturnsSpan() { using var mmf = new MMFile(@"Binaries/mmf_test.bin"); var s = mmf.AsSpan(0x16, 3); Assert.Equal(3, s.Length); Assert.Equal(0x11, s[0]); Assert.Equal(0x22, s[1]); Assert.Equal(0x33, s[2]); }
/// <summary> /// Append a <see cref="MMFile"/> to the list. /// </summary> /// <param name="addr">File address</param> /// <param name="data">File data</param> /// <param name="isCompressed">Is file compressed</param> /// <param name="isStatic">Is file address static</param> /// <returns>File index</returns> public static int AppendFile(int addr, byte[] data, bool isCompressed = false, bool isStatic = false) { var file = new MMFile { Addr = addr, End = addr + data.Length, IsCompressed = isCompressed, Data = data, IsStatic = isStatic, }; return(AppendFile(file)); }
/// <summary> /// Applies the given filename patch to the in-memory RomData /// </summary> /// <param name="filename"></param> /// <returns>SHA256 hash of the patch.</returns> public static byte[] ApplyPatch(string filename) { var hashAlg = new SHA256Managed(); using (var filestream = File.Open(filename, FileMode.Open)) using (var cryptoStream = new CryptoStream(filestream, hashAlg, CryptoStreamMode.Read)) using (var decompressStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) using (var memoryStream = new MemoryStream()) { decompressStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using (var reader = new BinaryReader(memoryStream)) { while (reader.BaseStream.Position != reader.BaseStream.Length) { var fileIndex = ReadWriteUtils.ReadS32(reader); var index = ReadWriteUtils.ReadS32(reader); var length = ReadWriteUtils.ReadS32(reader); var data = reader.ReadBytes(length); if (fileIndex >= RomData.MMFileList.Count) { var start = RomData.MMFileList[RomData.MMFileList.Count - 1].End; var newFile = new MMFile { Addr = start, IsCompressed = false, Data = data, End = start + data.Length }; RomData.MMFileList.Add(newFile); } if (index == -1) { RomData.MMFileList[fileIndex].Data = data; if (data.Length == 0) { RomData.MMFileList[fileIndex].Cmp_Addr = -1; RomData.MMFileList[fileIndex].Cmp_End = -1; } } else { CheckCompressed(fileIndex); ReadWriteUtils.Arr_Insert(data, 0, data.Length, RomData.MMFileList[fileIndex].Data, index); } } } return(hashAlg.Hash); } }
/// <summary> /// Try to parse the PE file. Best option for large files, /// as a memory mapped file is used. /// </summary> /// <param name="buff">Memory mapped file containing a possible PE file.</param> /// <param name="peFile">Parsed PE file or Null.</param> /// <returns>True if parable PE file and false if not.</returns> public static bool TryParse(MMFile file, out PeFile?peFile) { peFile = null; if (!IsPeFile(file)) { return(false); } try { peFile = new PeFile(file); } catch { return(false); } return(true); }
public void TryParse_GivenMMF_TrueOrFalse(string file, bool expected) { using var mmf = new MMFile(file); var actual = PeFile.TryParse(mmf, out var peFile); Assert.Equal(expected, actual); if (expected) { Assert.NotNull(peFile); } else { Assert.Null(peFile); } }
/// <summary> /// Append a <see cref="MMFile"/> to the list. /// </summary> /// <param name="file">File</param> /// <returns>File index</returns> public static int AppendFile(MMFile file) { if (!file.IsStatic) { // Insert before static files var index = GetTailFileIndex() + 1; RomData.MMFileList.Insert(index, file); return(index); } else { RomData.MMFileList.Add(file); return(RomData.MMFileList.Count - 1); } }
private static int AddNewFile(string filename) { MMFile newfile = new MMFile(); newfile.Addr = MMFileList[MMFileList.Count - 1].End; newfile.IsCompressed = false; BinaryReader data = new BinaryReader(File.Open(filename, FileMode.Open)); int len = (int)data.BaseStream.Length; newfile.Data = new byte[len]; data.Read(newfile.Data, 0, len); data.Close(); newfile.End = newfile.Addr + len; MMFileList.Add(newfile); return(newfile.Addr); }
/// <summary> /// Create a special <see cref="MMFile"/> with serialized <see cref="Symbols"/> data. /// </summary> /// <returns>MMFile</returns> public MMFile CreateMMFile() { var start = MMFILE_START; var data = this.ToBytes(); var file = new MMFile { Addr = (int)start, End = (int)start + data.Length, IsCompressed = false, IsStatic = true, Data = data, }; return(file); }
/// <summary> /// Create a <see cref="MMFile"/> from patch data. /// </summary> /// <param name="symbols">Symbols</param> /// <returns>MMFile</returns> public MMFile CreateMMFile(Symbols symbols) { var start = symbols.PayloadStart; var end = symbols.PayloadEnd; var data = GetFileData(start, end - start); var file = new MMFile { Addr = (int)start, End = (int)start + data.Length, IsCompressed = false, IsStatic = true, Data = data, }; return(file); }
public static int AddNewFile(string filename) { byte[] buffer; using (BinaryReader data = new BinaryReader(File.Open(filename, FileMode.Open))) { int len = (int)data.BaseStream.Length; buffer = new byte[len]; data.Read(buffer, 0, len); } int start = RomData.MMFileList[RomData.MMFileList.Count - 1].End; MMFile newfile = new MMFile { Addr = start, IsCompressed = false, Data = buffer, End = start + buffer.Length }; RomData.MMFileList.Add(newfile); return(newfile.Addr); }
public static void ReadFileTable(BinaryReader ROM) { MMFileList = new List <MMFile>(); ROM.BaseStream.Seek(FileTable, 0); while (true) { MMFile Current_File = new MMFile(); Current_File.Addr = (int)ReadU32(ROM); Current_File.End = (int)ReadU32(ROM); if (Current_File.Addr == Current_File.End) { break; } ; Current_File.Cmp_Addr = (int)ReadU32(ROM); Current_File.Cmp_End = (int)ReadU32(ROM); Current_File.IsCompressed = (Current_File.Cmp_End != 0); MMFileList.Add(Current_File); } ; ExtractAll(ROM); }
public static void ReadFileTable(BinaryReader ROM) { RomData.MMFileList = new List <MMFile>(); ROM.BaseStream.Seek(FILE_TABLE, SeekOrigin.Begin); while (true) { MMFile Current_File = new MMFile { Addr = ReadWriteUtils.ReadS32(ROM), End = ReadWriteUtils.ReadS32(ROM), Cmp_Addr = ReadWriteUtils.ReadS32(ROM), Cmp_End = ReadWriteUtils.ReadS32(ROM) }; Current_File.IsCompressed = Current_File.Cmp_End != 0; if (Current_File.Addr == Current_File.End) { break; } RomData.MMFileList.Add(Current_File); } ExtractAll(ROM); }
public static void InsertObj(byte[] obj, int replace) { int f = AddrToFile((uint)ObjTable); CheckCompressed(f); int basea = ObjTable - MMFileList[f].Addr; uint replaceaddr = Arr_ReadU32(MMFileList[f].Data, basea + (replace * 8)); int objf = MMFileList.FindIndex(u => u.Addr == replaceaddr); if (objf == -1) { return; } ; if (obj.Length > (MMFileList[objf].End - MMFileList[objf].Addr)) { MMFile newfile = new MMFile(); newfile.Addr = MMFileList[MMFileList.Count - 1].End; newfile.End = newfile.Addr + obj.Length; newfile.IsCompressed = true; newfile.WasEdited = true; newfile.Data = obj; MMFileList[objf].Cmp_Addr = -1; MMFileList[objf].Cmp_End = -1; MMFileList[objf].Data = null; MMFileList[objf].IsCompressed = false; MMFileList.Add(newfile); Arr_WriteU32(MMFileList[f].Data, basea + (replace * 8), (uint)newfile.Addr); Arr_WriteU32(MMFileList[f].Data, basea + (replace * 8) + 4, (uint)newfile.End); } else { MMFileList[objf].Data = obj; MMFileList[objf].WasEdited = true; }; }