예제 #1
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Try to read the initial and final calibration IDs
        /// </summary>
        private bool TryReadCalibrationChange(Blob blob, ref int offset)
        {
            uint tempUInt32 = 0;

            if (!blob.TryGetUInt32(ref tempUInt32, ref offset))
            {
                Trace.WriteLine("This patch file's metadata is way too short (no calibration metadata).");
                return false;
            }

            if (tempUInt32 != calibrationIdPrefix)
            {
                Trace.WriteLine(String.Format("Expected calibration id prefix {0:X8}, found {1:X8}", calibrationIdPrefix, tempUInt32));
                return false;
            }

            if (!blob.TryGetUInt32(ref tempUInt32, ref offset))
            {
                Trace.WriteLine("This patch file's metadata is way too short (no calibration address).");
                return false;
            }

            uint calibrationAddress = tempUInt32;

            if (!blob.TryGetUInt32(ref tempUInt32, ref offset))
            {
                Trace.WriteLine("This patch file's metadata is way too short (no calibration length).");
                return false;
            }

            uint calibrationLength = tempUInt32;

            string initialCalibrationId;
            if (!this.TryReadCalibrationId(blob, ref offset, out initialCalibrationId))
            {
                return false;
            }

            this.InitialCalibrationId = initialCalibrationId;

            string finalCalibrationId;
            if (!this.TryReadCalibrationId(blob, ref offset, out finalCalibrationId))
            {
                return false;
            }

            this.FinalCalibrationId = finalCalibrationId;

            // Synthesize calibration-change patch and blobs.
            Patch patch = new Patch( "Calibration ID Patch",
                calibrationAddress,
                calibrationAddress + (calibrationLength - 1));

            patch.IsMetaChecked = true;

            patch.Baseline = new Blob(
                calibrationAddress + Mod.BaselineOffset,
                Encoding.ASCII.GetBytes(initialCalibrationId));

            patch.Payload = new Blob(
                calibrationAddress,
                Encoding.ASCII.GetBytes(finalCalibrationId));

            this.patchList.AddPatch(patch);

            return true;
        }
예제 #2
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Given a patch, look up the content Blob and write it into the ROM.
        /// </summary>
        private bool TryApplyPatch(Patch patch, Stream romStream)
        {
            romStream.Seek(patch.StartAddress, SeekOrigin.Begin);

            if (patch.Payload == null)
            {
                Trace.WriteLine(String.Format("No blob found for patch starting at {0:X8}", patch.StartAddress));
                return false;
            }

            if (patch.StartAddress + patch.Payload.Content.Count != patch.EndAddress + 1)

            {
                Trace.WriteLine(String.Format("Payload blob for patch starting at {0:X8} does not contain the entire patch.", patch.StartAddress));
                Trace.WriteLine(String.Format("Patch start {0:X8}, end {1:X8}, length {2:X8}", patch.StartAddress, patch.EndAddress, patch.Length));
                Trace.WriteLine(String.Format("Payload blob length {2:X8}", patch.Payload.Content.Count));
                return false;
            }

            romStream.Write(patch.Payload.Content.ToArray(), 0, (int) patch.Payload.Content.Count);
            return true;
        }
예제 #3
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Print the current contents of the ROM in the address range for the given patch.
        /// Contains a check against metadata when IsMetaChecked = true
        /// </summary>
        private bool TryCheckPrintBaseline(Patch patch, Stream outStream)
        {
            uint patchLength = patch.Length;
            byte[] buffer = new byte[patchLength];

            //read baseline ROM data blob into buffer
            if (!this.TryReadBuffer(outStream, patch.StartAddress, buffer))
            {
                return false;
            }

               if (patch.IsMetaChecked)
            {
                patch.MetaCheck((IEnumerable<byte>)buffer);
            }

            using ( StreamWriter textWriter = File.AppendText(this.ModIdent + ".patch"))
            {
                //TextWriter textWriter = new StreamWriter(consoleOutputStream);

                //OUTPUT DIRECT TO FILE, ADD VERSIONING SYSTEM

                SRecordWriter writer = new SRecordWriter(textWriter);

                // The "baselineOffset" delta is how we distinguish baseline data from patch data.

                writer.Write(patch.StartAddress + BaselineOffset, buffer);
            }

            return true;
        }
예제 #4
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Construct a Pull JSR HOOK patch from the metadata blob.
        /// </summary>
        private bool TrySynthesizePullJsrHookPatch(Blob metadata, out Patch patch, ref int offset, List<Blob> blobs)
        {
            uint address = 0;
            string name;

            if (!metadata.TryGetUInt32(ref address, ref offset))
            {
                throw new InvalidDataException("This patch's metadata contains an incomplete 4-byte patch record (no address).");
            }

            if (!TryReadMetaString(metadata, out name, ref offset))
            {
                Trace.WriteLine("Patch at metadata offset: " + offset + "contains invalid name."); name ="UNKNOWN PATCH";
            }

            byte[] jsrbytes = new byte[] {0xF0,0x48,0x00,0x09};

            patch = new PullJSRHookPatch(name, address, address + 3);

            patch.IsMetaChecked = true;//remove thsi

            patch.Payload = new Blob(patch.StartAddress, jsrbytes);

            //this.blobs.Add(new Blob(address, BitConverter.GetBytes(newValue).Reverse()));
            //this.blobs.Add(new Blob(address + BaselineOffset, BitConverter.GetBytes(oldValue).Reverse()));
            return true;
        }
예제 #5
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Determine whether the bytes from a Patch's expected data match the contents of the ROM.
        /// </summary>
        private bool ValidateBytes(Patch patch, Stream romStream)
        {
            uint patchLength = patch.Length;
            byte[] buffer = new byte[patchLength];
            if (!this.TryReadBuffer(romStream, patch.StartAddress, buffer))
            {
                Console.Write("tryreadbuffer failed in validatebytes");
                return false;
            }

            //            DumpBuffer("Actual  ", buffer, buffer.Length);
            //            DumpBuffer("Expected", expectedData.Content, buffer.Length);

            int mismatches = 0;
            byte expected;

            for (int index = 0; index < patchLength; index++)
            {
                byte actual = buffer[index];

                if (!patch.IsNewPatch)
                {
                    if (index >= patch.Baseline.Content.Count)
                    {
                        Trace.WriteLine("Expected data is smaller than patch size.");
                        return false;
                    }

                    expected = patch.Baseline.Content[index];
                }
                else
                    expected = 0xFF;

                if (actual != expected)
                {
                    mismatches++;
                }
            }

            if (mismatches == 0)
            {
                Trace.WriteLine("Valid.");
                return true;
            }

            Trace.WriteLine("Invalid.");
            Trace.WriteLine(String.Format("{0} bytes (of {1}) do not meet expectations.", mismatches, patchLength));
            return false;
        }
예제 #6
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Construct a Last 2 of 4-byte patch from the metadata blob.
        /// </summary>
        private bool TrySynthesizeLast2Of4BytePatch(Blob metadata, out Patch patch, ref int offset)
        {
            uint address = 0;
            uint oldValue = 0;
            uint newValue = 0;
            string name;

            if (!metadata.TryGetUInt32(ref address, ref offset))
            {
                throw new InvalidDataException("This patch's metadata contains an incomplete l2o4-byte patch record (no address).");
            }

            if (!metadata.TryGetUInt32(ref oldValue, ref offset))
            {
                throw new InvalidDataException("This patch's metadata contains an incomplete l2o4-byte patch record (no baseline value).");
            }

            if (!metadata.TryGetUInt32(ref newValue, ref offset))
            {
                throw new InvalidDataException("This patch's metadata contains an incomplete l2o4-byte patch record (no patch value).");
            }

            if (!TryReadMetaString(metadata, out name, ref offset))
            {
                Trace.WriteLine("Patch at metadata offset: " + offset + "contains invalid name."); name ="UNKNOWN PATCH";
            }

            patch = new Patch(name, address + 2, address + 3);
            patch.IsMetaChecked = true;
            patch.Baseline = new Blob(address + 2 + BaselineOffset, BitConverter.GetBytes(oldValue).Take(2).Reverse());
            patch.Payload = new Blob(address + 2, BitConverter.GetBytes(newValue).Take(2).Reverse());

            return true;
        }
예제 #7
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        /// <summary>
        /// Read a single Patch from the metadata blob.
        /// </summary>
        /// <remarks>
        /// Consider returning false, printing error message.  But, need to 
        /// be certain to abort the whole process at that point...
        /// </remarks>
        private bool TryReadPatch(Blob metadata, out Patch patch, ref int offset, List<Blob> blobs )
        {
            uint start = 0;
            uint end = 0;
            string name;

            if (!metadata.TryGetUInt32(ref start, ref offset))
            {
                throw new InvalidDataException("Patch at metadata offset: " + offset + " contains an incomplete patch record (no start address).");
            }

            if (!metadata.TryGetUInt32(ref end, ref offset))
            {
                throw new InvalidDataException("Patch at metadata offset: " + offset + " contains an incomplete patch record (no end address).");
            }

            if(!TryReadMetaString(metadata,out name, ref offset))
            {
                Trace.WriteLine("Patch at metadata offset: " + offset + "contains invalid name."); name ="UNKNOWN PATCH";
            }

            patch = new Patch(name,start, end);

            Blob baselineBlob;

            if (!this.TryGetPatchBlob(patch.StartAddress + BaselineOffset, patch.Length, out baselineBlob, blobs))
            {
                if (baselineBlob != null)  return false;
            }

                patch.Baseline = baselineBlob;

            Blob payloadBlob;
            if (!this.TryGetPatchBlob(patch.StartAddress, patch.Length, out payloadBlob, blobs))
            {
                return false;
            }

            patch.Payload = payloadBlob;
            return true;
        }
예제 #8
0
파일: Mod.cs 프로젝트: segapsh2/SharpTune
        private bool TryReadMetaHeader8(Blob metadata, ref int offset)
        {
            UInt32 cookie = 0;
            uint tempInt = 0;
            Patch patch = null;
            while ((metadata.Content.Count > offset + 8) &&
                metadata.TryGetUInt32(ref cookie, ref offset))
            {
                if (cookie == Mod.calibrationIdPrefix)
                {
                    if (!metadata.TryGetUInt32(ref tempInt, ref offset))
                    {
                        Trace.WriteLine("This patch file's metadata is way too short (no calibration address).");
                        return false;
                    }

                    this.CalIdAddress = tempInt;

                    if (!metadata.TryGetUInt32(ref tempInt, ref offset))
                    {
                        Trace.WriteLine("This patch file's metadata is way too short (no calibration length).");
                        return false;
                    }

                    this.CalIdLength = tempInt;

                    string initialCalibrationId;
                    if (!this.TryReadCalibrationId(metadata, ref offset, out initialCalibrationId))
                    {
                        return false;
                    }

                    this.InitialCalibrationId = initialCalibrationId;

                    string finalCalibrationId;
                    if (!this.TryReadCalibrationId(metadata, ref offset, out finalCalibrationId))
                    {
                        return false;
                    }

                    if (finalCalibrationId.ContainsCI("ffffffff"))
                    {
                        StringBuilder s = new StringBuilder(initialCalibrationId, 0,initialCalibrationId.Length, initialCalibrationId.Length);
                        s.Remove(initialCalibrationId.Length-2,2);
                        s.Insert(initialCalibrationId.Length-2,"MM");
                        FinalCalibrationId = s.ToString();
                    }

                    this.FinalCalibrationId = finalCalibrationId;
                    // Synthesize calibration-change patch and blobs.
                    patch = new Patch( "Calibration ID Patch",
                        CalIdAddress,
                        CalIdAddress + (CalIdLength - 1));

                    patch.IsMetaChecked = true;

                    patch.Baseline = new Blob(
                        CalIdAddress + Mod.BaselineOffset,
                        Encoding.ASCII.GetBytes(initialCalibrationId));

                    patch.Payload = new Blob(
                        CalIdAddress,
                        Encoding.ASCII.GetBytes(finalCalibrationId));

                    this.patchList.AddPatch(patch);
                }
                else if (cookie == modIdPrefix)
                {
                    if (metadata.TryGetUInt32(ref tempInt, ref offset))
                    {
                        this.ModIdentAddress = tempInt;
                    }
                    string metaString = null;
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found modName, output to string!
                        this.ModIdent = metaString;
                    }
                }
                else if (cookie == ecuIdPrefix)
                {
                    if (metadata.TryGetUInt32(ref tempInt, ref offset))
                    {
                        this.EcuIdAddress = tempInt;
                    }
                    if (metadata.TryGetUInt32(ref tempInt, ref offset))
                    {
                        this.EcuIdLength = tempInt;
                    }
                    string metaString = null;
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found modName, output to string!
                        this.InitialEcuId = metaString;
                    }
                    metadata.TryGetUInt32(ref tempInt, ref offset);
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found modName, output to string!
                        this.FinalEcuId = metaString;
                    }
                }
                else if (cookie == modAuthorPrefix)
                {
                    string metaString = null;
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found modName, output to string!
                        this.ModAuthor = metaString;
                    }
                    else
                    {
                        Trace.WriteLine("Invalid patch found." + patch.ToString());
                        return false;
                    }
                }
                else if (cookie == modBuildPrefix)
                {
                    string metaString = null;
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found modName, output to string!
                        this.ModBuild = metaString;
                    }
                    else
                    {
                        Trace.WriteLine("Invalid patch found." + patch.ToString());
                        return false;
                    }
                }
                else if (cookie == modInfoPrefix)
                {
                    string metaString = null;
                    if (this.TryReadMetaString(metadata, out metaString, ref offset))
                    {
                        // found Trace.WriteLine("Patch at metadata offset: " + offset + "contains invalid name."); name ="UNKNOWN PATCH";, output to string!
                        this.ModInfo = metaString.Replace("__", Environment.NewLine);
                    }
                    else
                    {
                        Trace.WriteLine("Invalid ModInfo found." + patch.ToString());
                        return false;
                    }
                }
                else if (cookie == endoffile)
                {
                    break;
                }
            }
            if (this.InitialEcuId.Length == this.FinalEcuId.Length)
            {
                // Synthesize calibration-change patch and blobs.
                if (FinalEcuId.ContainsCI("ffffffff"))
                {
                    StringBuilder feid = new StringBuilder(Regex.Split(this.ModIdent,".v")[1].Replace(".", ""));
                    while (feid.Length < this.InitialEcuId.Length)
                    {
                        feid.Append("F");
                    }
                    this.FinalEcuId = feid.ToString();
                }
                patch = new Patch( "ECU ID Patch",
                    EcuIdAddress,
                    EcuIdAddress + ((EcuIdLength / 2) - 1));

                patch.IsMetaChecked = true;

                patch.Baseline = new Blob(
                    EcuIdAddress + Mod.BaselineOffset,
                    InitialEcuId.ToByteArray());

                patch.Payload = new Blob(
                    EcuIdAddress,
                    FinalEcuId.ToByteArray());

                this.patchList.AddPatch(patch);
            }
            if (this.patchList.Count < 2)
            {
                Trace.WriteLine("This patch file's metadata contains no CALID or ECUID patch!!.");
                return false;
            }
            return true;
        }
예제 #9
0
파일: Verifier.cs 프로젝트: Merp/SharpTune
        private bool TryProcessRecord(Patch patch, SRecord record)
        {
            if (record.Payload == null)
            {
                return true;
            }

            int startAddress = (int)(this.apply ? patch.StartAddress : patch.StartAddress + Mod.BaselineOffset);
            int endAddress = (int)(this.apply ? patch.EndAddress : patch.EndAddress + Mod.BaselineOffset);

            for (uint address = record.Address; address < record.Address + record.Payload.Length; address++)
            {
                if (address >= startAddress && address <= endAddress)
                {
                    this.romStream.Position = address;
                    int i = this.romStream.ReadByte();
                    if (i == -1)
                    {
                        Trace.WriteLine(String.Format("Reached end of file while trying to verify address {0:X8}", address));
                        return false;
                    }

                    int recordAddresss = (int)(this.apply ? record.Address : record.Address - Mod.BaselineOffset);

                    uint payloadIndex = address - record.Address;
                    byte b = record.Payload[payloadIndex];
                    if (i != b)
                    {
                        Trace.WriteLine(String.Format("Address {0:X8} contains {1:X2}, but should contain {2:X2}", address, b, payloadIndex));
                        return false;
                    }
                }
            }

            return true;
        }
예제 #10
0
파일: Verifier.cs 프로젝트: Merp/SharpTune
        private bool TryVerifyPatch(Patch patch)
        {
            // using (this.patchReader)
            //using (this.romStream)
            //{
              //  this.patchReader.Open();
                SRecord record;
                while (this.patchReader.TryReadNextRecord(out record))
                {
                    if (!this.TryProcessRecord(patch, record))
                    {
                        Dispose();
                        return false;
                    }
                }

                Dispose();
                return true;
        }