using System;
using System.Linq;
namespace WhiteMagic.Hooking;
///
/// A single reversible byte patch. Captures the original bytes when applied,
/// restores them when removed, and reports its state by comparing live memory.
///
public sealed class Patch : IDisposable
{
private readonly MemoryBase _memory;
/// The unique name of this patch.
public string Name { get; }
/// The address the patch overwrites.
public IntPtr Address { get; }
/// The bytes written by the patch.
public byte[] PatchBytes { get; }
/// The bytes captured before the patch was applied.
public byte[]? OriginalBytes { get; private set; }
///
/// when the live bytes at match
/// .
///
public bool IsApplied
{
get
{
byte[] current = _memory.ReadBytes(Address, PatchBytes.Length);
return current.SequenceEqual(PatchBytes);
}
}
internal Patch(MemoryBase memory, string name, IntPtr address, byte[] patchBytes)
{
ArgumentNullException.ThrowIfNull(patchBytes);
_memory = memory;
Name = name;
Address = address;
PatchBytes = patchBytes;
}
/// Captures the original bytes and writes the patch bytes.
public void Apply()
{
if (IsApplied)
return;
OriginalBytes = _memory.ReadBytes(Address, PatchBytes.Length);
_memory.WriteBytes(Address, PatchBytes);
}
/// Restores the original bytes if they were captured.
public void Remove()
{
if (OriginalBytes is null)
return;
_memory.WriteBytes(Address, OriginalBytes);
OriginalBytes = null;
}
///
public void Dispose()
{
Remove();
}
}