ReadValue<T>
, ReadString
, ReadPointer
: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/ProcessExtensions.cs
// "address" is an IntPtr to an int value
int intValue = game.ReadValue<int>(address);
// "address" is an IntPtr to a string, "64" is the maximum amount of bytes to read
string strValue = game.ReadString(address, 64);
// "address" is an IntPtr to another address (for example a class)
IntPtr ptrValue = game.ReadPointer(address);
DeepPointer
: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/DeepPointer.cs
var deepPointer = new DeepPointer("Celeste.exe", 0x4A03598, 0xAC, 0x18);
int intValue = deepPointer.Deref<int>(game);
string strValue = deepPointer.DerefString(game, 64);
IntPtr ptrValue = IntPtr.Zero;
bool success = deepPointer.DerefOffsets(game, out ptrValue);
MemoryWatcher<T>
, StringWatcher
: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/MemoryWatcher.cs
// initializes a list of MemoryWatchers
vars.Watchers = new MemoryWatcherList
{
// adds a Watcher to the list; additionally use of vars.Watchers.Add(MemoryWatcher) is possible
new MemoryWatcher<int>(new DeepPointer("Celeste.exe", 0x4A03598, 0xAC, 0x18)) { Name = "intWatcher" },
new MemoryWatcher<float>(address) { Name = "floatWatcher" },
new StringWatcher(deepPointer, 64) { Name = "stringWatcher" }
};
// updates all Watchers in the list (use this in update {})
vars.Watchers.UpdateAll(game);
// access a Watcher's values
vars.Watchers["intWatcher"].Current; // retrieves the value at this Watcher's address on the current update
vars.Watchers["intWatcher"].Old; // retrieves the value at this Watcher's address on the previous update
vars.Watchers["intWatcher"].Changed; // checks whether .Current and .Old are not equal
SignatureScanner
, SigScanTarget
, MemoryPages
: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/SignatureScanner.cs
var mainModule = modules.First();
// initializes a new scanner with the target process, the start address, and the amount of bytes to search
var scanner = new SignatureScanner(game, mainModule.BaseAddress, mainModule.ModuleMemorySize);
// initializes a new signature target with the offset (added to the address when found) and the pattern
var target = new SigScanTarget(10, "13 37 13 ?? ?? 37 13 37");
// optionally, some code which gets executed upon a successful find can be defined:
// this code returns the address relative to another one in a 64-bit process
target.OnFound = (proc, scanner, address) =>
{
return address + 0x4 + proc.ReadValue<int>(address);
};
// scans the bytes in the scanner for the target and returns the first address at which it was found
IntPtr result = scanner.Scan(target);
// returns all addresses which matched the target
var results = scanner.ScanAll(target);
// scans all of the game's memory pages to search for a successful scan
foreach (var page in game.MemoryPages(false))
{
var scanner = new SignatureScanner(game, page.BaseAddress, (int)(page.RegionSize));
result = scanner.Scan(target);
if (result != IntPtr.Zero)
break;
}
Super helpful. Thanks Ero.