/// <summary> /// Constructor. /// </summary> public Patcher(SRecordReader reader, Stream romStream) { this.reader = reader; this.romStream = romStream; this.blobs = new List <Blob>(); this.patches = new List <Patch>(); }
/// <summary> /// Dump the contents of an SRecord file. Mostly intended for development use. /// </summary> private static bool TryDumpSRecordFile(string path) { bool result = true; SRecord record; SRecordReader reader = new SRecordReader(path); reader.Open(); BlobList list = new BlobList(); while (reader.TryReadNextRecord(out record)) { if (!record.IsValid) { Console.WriteLine(record.ToString()); result = false; continue; } list.ProcessRecord(record); Console.WriteLine(record.ToString()); } Console.WriteLine("Aggregated:"); foreach (Blob blob in list.Blobs) { Console.WriteLine(blob.ToString()); } return(result); }
public void Dispose() { if (this.patchReader != null) { this.patchReader.Dispose(); this.patchReader = null; } if (this.romStream != null) { this.romStream.Dispose(); this.romStream = null; } }
/// <summary> /// Extract data from an unpatched ROM file, for inclusion in a patch file. /// </summary> private static bool TryGenerateBaseline(string patchPath, string romPath) { SRecordReader reader = new SRecordReader(patchPath); Stream romStream = File.OpenRead(romPath); Patcher patcher = new Patcher(reader, romStream); if (!patcher.TryReadPatches()) { return(false); } // Handy for manual work, but with this suppressed, you can append-pipe the output to the patch file. // Console.WriteLine("Generating baseline SRecords for:"); // patcher.PrintPatches(); return(patcher.TryPrintBaselines()); }
private bool TryVerifyPatch(Patch patch) { using (this.patchReader = new SRecordReader(patchPath)) using (this.romStream = File.OpenRead(romPath)) { this.patchReader.Open(); SRecord record; while (this.patchReader.TryReadNextRecord(out record)) { if (!this.TryProcessRecord(patch, record)) { return(false); } } return(true); } }
/// <summary> /// Determine whether a patch is suitable for a ROM, and optionally apply the patch if so. /// </summary> private static bool TryApply(string patchPath, string romPath, bool apply, bool commit) { SRecordReader reader = new SRecordReader(patchPath); Stream romStream; string workingPath = romPath + ".temp"; if (commit) { File.Copy(romPath, workingPath, true); romStream = File.Open(workingPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); } else { romStream = File.OpenRead(romPath); } Patcher patcher = new Patcher(reader, romStream); if (!patcher.TryReadPatches()) { return(false); } Console.WriteLine("This patch file was intended for: {0}.", patcher.InitialCalibrationId); Console.WriteLine("This patch file converts ROM to: {0}.", patcher.FinalCalibrationId); if (!apply) { Console.WriteLine("Preparing to remove patch."); patcher.TryReversePatches(); } if (!patcher.TryVerifyExpectedData()) { if (apply) { Console.WriteLine("This patch file can NOT be applied to this ROM file."); } else { Console.WriteLine("This patch file was NOT previously applied to this ROM file."); } return(false); } if (apply) { Console.WriteLine("This patch file can be applied to this ROM file."); } else { Console.WriteLine("This patch file was previously applied to this ROM file."); } if (!commit) { return(true); } if (apply) { Console.WriteLine("Applying patch."); } else { Console.WriteLine("Removing patch."); } if (patcher.TryApplyPatches()) { reader.Dispose(); romStream.Dispose(); Console.WriteLine("Verifying patch."); using (Verifier verifier = new Verifier(patchPath, workingPath, apply)) { if (!verifier.TryVerify(patcher.Patches)) { Console.WriteLine("Verification failed, ROM file not modified."); return(false); } } File.Copy(workingPath, romPath, true); Console.WriteLine("ROM file modified successfully."); } else { Console.WriteLine("The ROM file has not been modified."); } return(true); }