示例#1
0
 /// <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>();
 }
示例#2
0
        /// <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);
        }
示例#3
0
        public void Dispose()
        {
            if (this.patchReader != null)
            {
                this.patchReader.Dispose();
                this.patchReader = null;
            }

            if (this.romStream != null)
            {
                this.romStream.Dispose();
                this.romStream = null;
            }
        }
示例#4
0
        /// <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());
        }
示例#5
0
        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);
                }
        }
示例#6
0
        /// <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);
        }