예제 #1
0
 public IpsPatcher(BinaryReader reader)
 {
     _patches = ParseIps(reader);
     if (_patches != null)
     {
         Logger.Info?.Print(LogClass.ModLoader, "IPS patch loaded successfully");
     }
 }
예제 #2
0
        /// <summary>
        /// Adds all patches from an existing MemPatch
        /// </summary>
        /// <param name="patches">The patches to add</param>
        public void AddFrom(MemPatch patches)
        {
            if (patches == null)
            {
                return;
            }

            foreach (var(patchOffset, patch) in patches._patches)
            {
                _patches[patchOffset] = patch;
            }
        }
예제 #3
0
        private MemPatch Parse()
        {
            if (_reader == null)
            {
                return(null);
            }

            MemPatch patches = new MemPatch();

            bool enabled      = false;
            bool printValues  = false;
            int  offset_shift = 0;

            string line;
            int    lineNum = 0;
예제 #4
0
        private static MemPatch ParseIps(BinaryReader reader)
        {
            Span <byte> IpsHeaderMagic   = Encoding.ASCII.GetBytes("PATCH").AsSpan();
            Span <byte> IpsTailMagic     = Encoding.ASCII.GetBytes("EOF").AsSpan();
            Span <byte> Ips32HeaderMagic = Encoding.ASCII.GetBytes("IPS32").AsSpan();
            Span <byte> Ips32TailMagic   = Encoding.ASCII.GetBytes("EEOF").AsSpan();

            MemPatch patches = new MemPatch();
            var      header  = reader.ReadBytes(IpsHeaderMagic.Length).AsSpan();

            if (header.Length != IpsHeaderMagic.Length)
            {
                return(null);
            }

            bool        is32;
            Span <byte> tailSpan;

            if (header.SequenceEqual(IpsHeaderMagic))
            {
                is32     = false;
                tailSpan = IpsTailMagic;
            }
            else if (header.SequenceEqual(Ips32HeaderMagic))
            {
                is32     = true;
                tailSpan = Ips32TailMagic;
            }
            else
            {
                return(null);
            }

            byte[] buf = new byte[tailSpan.Length];

            bool ReadNext(int size) => reader.Read(buf, 0, size) != size;

            while (true)
            {
                if (ReadNext(buf.Length))
                {
                    return(null);
                }

                if (buf.AsSpan().SequenceEqual(tailSpan))
                {
                    break;
                }

                int patchOffset = is32 ? buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]
                                       : buf[0] << 16 | buf[1] << 8 | buf[2];

                if (ReadNext(2))
                {
                    return(null);
                }

                int patchSize = buf[0] << 8 | buf[1];

                if (patchSize == 0) // RLE/Fill mode
                {
                    if (ReadNext(2))
                    {
                        return(null);
                    }

                    int fillLength = buf[0] << 8 | buf[1];

                    if (ReadNext(1))
                    {
                        return(null);
                    }

                    patches.AddFill((uint)patchOffset, fillLength, buf[0]);
                }
                else // Copy mode
                {
                    var patch = reader.ReadBytes(patchSize);

                    if (patch.Length != patchSize)
                    {
                        return(null);
                    }

                    patches.Add((uint)patchOffset, patch);
                }
            }

            return(patches);
        }
예제 #5
0
 public void AddPatches(MemPatch patches)
 {
     patches.AddFrom(_patches);
 }