Improve performance by about 5x by not creating a new process handle for every memory read.
This commit is contained in:
parent
ae893f02e4
commit
9cc32bcfc5
@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace rabi_splitter_WPF
|
||||
{
|
||||
public static class MemoryHelper
|
||||
public class MemoryHelper : IDisposable
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
|
||||
@ -18,7 +18,26 @@ namespace rabi_splitter_WPF
|
||||
|
||||
private const int PROCESS_WM_READ = 0x0010;
|
||||
|
||||
public static T GetMemoryValue<T>(Process process, int addr,bool baseaddr=true)
|
||||
private readonly IntPtr processHandle;
|
||||
private readonly int processHandleInt;
|
||||
private readonly int baseAddress;
|
||||
|
||||
public MemoryHelper(Process process)
|
||||
{
|
||||
processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id);
|
||||
processHandleInt = (int)processHandle;
|
||||
baseAddress = process.MainModule.BaseAddress.ToInt32();
|
||||
}
|
||||
|
||||
/*
|
||||
public static T GetMemoryValue<T>(Process process, int addr, bool baseaddr = true)
|
||||
{
|
||||
var memoryHelper = new MemoryHelper(process);
|
||||
return memoryHelper.GetMemoryValue<T>(addr, baseaddr);
|
||||
}
|
||||
*/
|
||||
|
||||
public T GetMemoryValue<T>(int addr, bool baseaddr = true)
|
||||
{
|
||||
int datasize;
|
||||
switch (Type.GetTypeCode(typeof(T)))
|
||||
@ -30,21 +49,24 @@ namespace rabi_splitter_WPF
|
||||
case TypeCode.SByte:
|
||||
datasize = 1;
|
||||
break;
|
||||
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.UInt16:
|
||||
datasize = 2;
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.UInt32:
|
||||
datasize = 4;
|
||||
break;
|
||||
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt64:
|
||||
datasize = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("not supported");
|
||||
}
|
||||
@ -52,17 +74,15 @@ namespace rabi_splitter_WPF
|
||||
byte[] buffer = new byte[datasize];
|
||||
int bytesRead = 0;
|
||||
|
||||
IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id);
|
||||
if (baseaddr)
|
||||
{ ReadProcessMemory((int) processHandle, process.MainModule.BaseAddress.ToInt32() + addr, buffer,
|
||||
datasize, ref bytesRead);}
|
||||
{
|
||||
ReadProcessMemory(processHandleInt, baseAddress + addr, buffer, datasize, ref bytesRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadProcessMemory((int)processHandle, addr, buffer,
|
||||
datasize, ref bytesRead);
|
||||
|
||||
ReadProcessMemory(processHandleInt, addr, buffer, datasize, ref bytesRead);
|
||||
}
|
||||
CloseHandle(processHandle);
|
||||
|
||||
switch (Type.GetTypeCode(typeof(T)))
|
||||
{
|
||||
|
||||
@ -102,5 +122,27 @@ namespace rabi_splitter_WPF
|
||||
}
|
||||
|
||||
|
||||
#region IDisposable Support
|
||||
private bool disposed = false;
|
||||
|
||||
protected virtual void DisposeUnmanagedResources()
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
CloseHandle(processHandle);
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
~MemoryHelper() {
|
||||
DisposeUnmanagedResources();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeUnmanagedResources();
|
||||
// GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -55,44 +55,44 @@ namespace rabi_splitter_WPF
|
||||
|
||||
public readonly int minimapPosition;
|
||||
|
||||
public MemorySnapshot(Process process, int veridx)
|
||||
public MemorySnapshot(MemoryHelper memoryHelper, int veridx)
|
||||
{
|
||||
t_playtime = MemoryHelper.GetMemoryValue<int>(process, StaticData.IGTAddr[veridx]);
|
||||
playtime = MemoryHelper.GetMemoryValue<int>(process, StaticData.PlaytimeAddr[veridx]);
|
||||
blackness = MemoryHelper.GetMemoryValue<int>(process, StaticData.BlacknessAddr[veridx]);
|
||||
t_playtime = memoryHelper.GetMemoryValue<int>(StaticData.IGTAddr[veridx]);
|
||||
playtime = memoryHelper.GetMemoryValue<int>(StaticData.PlaytimeAddr[veridx]);
|
||||
blackness = memoryHelper.GetMemoryValue<int>(StaticData.BlacknessAddr[veridx]);
|
||||
|
||||
mapid = MemoryHelper.GetMemoryValue<int>(process, StaticData.MapAddress[veridx]);
|
||||
musicid = MemoryHelper.GetMemoryValue<int>(process, StaticData.MusicAddr[veridx]);
|
||||
money = MemoryHelper.GetMemoryValue<int>(process, StaticData.MoneyAddress[veridx]);
|
||||
mapid = memoryHelper.GetMemoryValue<int>(StaticData.MapAddress[veridx]);
|
||||
musicid = memoryHelper.GetMemoryValue<int>(StaticData.MusicAddr[veridx]);
|
||||
money = memoryHelper.GetMemoryValue<int>(StaticData.MoneyAddress[veridx]);
|
||||
|
||||
carrotXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654BC);
|
||||
hammerXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654B4);
|
||||
ribbonXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654B8);
|
||||
itemPercent = MemoryHelper.GetMemoryValue<float>(process, 0xA730E8);
|
||||
carrotXp = memoryHelper.GetMemoryValue<int>(0xD654BC);
|
||||
hammerXp = memoryHelper.GetMemoryValue<int>(0xD654B4);
|
||||
ribbonXp = memoryHelper.GetMemoryValue<int>(0xD654B8);
|
||||
itemPercent = memoryHelper.GetMemoryValue<float>(0xA730E8);
|
||||
|
||||
minimapPosition = MemoryHelper.GetMemoryValue<int>(process, 0xA72E08);
|
||||
minimapPosition = memoryHelper.GetMemoryValue<int>(0xA72E08);
|
||||
|
||||
nAttackUps = countItems(process, 0xD6352C, 0xD63628);
|
||||
nHpUps = countItems(process, 0xD6342C, 0xD63528);
|
||||
nManaUps = countItems(process, 0xD6362C, 0xD63728);
|
||||
nPackUps = countItems(process, 0xD6382C, 0xD63928);
|
||||
nRegenUps = countItems(process, 0xD6372C, 0xD63828);
|
||||
nAttackUps = countItems(memoryHelper, 0xD6352C, 0xD63628);
|
||||
nHpUps = countItems(memoryHelper, 0xD6342C, 0xD63528);
|
||||
nManaUps = countItems(memoryHelper, 0xD6362C, 0xD63728);
|
||||
nPackUps = countItems(memoryHelper, 0xD6382C, 0xD63928);
|
||||
nRegenUps = countItems(memoryHelper, 0xD6372C, 0xD63828);
|
||||
|
||||
entityArrayPtr = MemoryHelper.GetMemoryValue<int>(process, StaticData.EnenyPtrAddr[veridx]);
|
||||
entityArrayPtr = memoryHelper.GetMemoryValue<int>(StaticData.EnenyPtrAddr[veridx]);
|
||||
|
||||
hp = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x4D8, false);
|
||||
maxhp = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x4E8, false);
|
||||
hp = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x4D8, false);
|
||||
maxhp = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x4E8, false);
|
||||
|
||||
currentSprite = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x654, false);
|
||||
actionFrame = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x660, false);
|
||||
currentSprite = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x654, false);
|
||||
actionFrame = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x660, false);
|
||||
|
||||
amulet = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x52C, false);
|
||||
boost = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x5DC, false);
|
||||
mana = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x6B8, false);
|
||||
stamina = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x5B4, false);
|
||||
amulet = memoryHelper.GetMemoryValue<float>(entityArrayPtr + 0x52C, false);
|
||||
boost = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x5DC, false);
|
||||
mana = memoryHelper.GetMemoryValue<float>(entityArrayPtr + 0x6B8, false);
|
||||
stamina = memoryHelper.GetMemoryValue<int>(entityArrayPtr + 0x5B4, false);
|
||||
|
||||
px = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0xC, false);
|
||||
py = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x10, false);
|
||||
px = memoryHelper.GetMemoryValue<float>(entityArrayPtr + 0xC, false);
|
||||
py = memoryHelper.GetMemoryValue<float>(entityArrayPtr + 0x10, false);
|
||||
|
||||
|
||||
// Read Entity Array and Search for boss data
|
||||
@ -103,16 +103,16 @@ namespace rabi_splitter_WPF
|
||||
int currArrayPtr = entityArrayPtr + entitySize * 4;
|
||||
for (int i=0; i<500; ++i) {
|
||||
// (Hard limit of reading 500 entries)
|
||||
int entityId = MemoryHelper.GetMemoryValue<int>(process,
|
||||
int entityId = memoryHelper.GetMemoryValue<int>(
|
||||
currArrayPtr + StaticData.EnenyEnitiyIDOffset[veridx], false);
|
||||
int entityMaxHp = MemoryHelper.GetMemoryValue<int>(process,
|
||||
int entityMaxHp = memoryHelper.GetMemoryValue<int>(
|
||||
currArrayPtr + StaticData.EnenyEnitiyMaxHPOffset[veridx], false);
|
||||
|
||||
if (entityId == 0 && entityMaxHp == 0) break;
|
||||
|
||||
int activeFlag = MemoryHelper.GetMemoryValue<int>(process,
|
||||
int activeFlag = memoryHelper.GetMemoryValue<int>(
|
||||
currArrayPtr + StaticData.EnenyEnitiyIsActiveOffset[veridx], false);
|
||||
int animationState = MemoryHelper.GetMemoryValue<int>(process,
|
||||
int animationState = memoryHelper.GetMemoryValue<int>(
|
||||
currArrayPtr + StaticData.EnenyEnitiyAnimationOffset[veridx], false);
|
||||
|
||||
bool isAlive = activeFlag == 1 && animationState >= 0;
|
||||
@ -122,7 +122,7 @@ namespace rabi_splitter_WPF
|
||||
BossStats boss;
|
||||
boss.entityArrayIndex = entityArraySize;
|
||||
boss.id = entityId;
|
||||
boss.hp = MemoryHelper.GetMemoryValue<int>(process, currArrayPtr + StaticData.EnenyEnitiyHPOffset[veridx], false);
|
||||
boss.hp = memoryHelper.GetMemoryValue<int>(currArrayPtr + StaticData.EnenyEnitiyHPOffset[veridx], false);
|
||||
boss.type = StaticData.GetBoss(entityId).Value;
|
||||
boss.maxHp = entityMaxHp;
|
||||
|
||||
@ -136,12 +136,12 @@ namespace rabi_splitter_WPF
|
||||
}
|
||||
}
|
||||
|
||||
private int countItems(Process process, int addrFirst, int addrLast)
|
||||
private int countItems(MemoryHelper memoryHelper, int addrFirst, int addrLast)
|
||||
{
|
||||
int count = 0;
|
||||
for (int addr = addrFirst; addr <= addrLast; ++addr)
|
||||
{
|
||||
count += MemoryHelper.GetMemoryValue<int>(process, addr) == 1 ? 1 : 0;
|
||||
count += memoryHelper.GetMemoryValue<int>(addr) == 1 ? 1 : 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -38,17 +38,20 @@ namespace rabi_splitter_WPF
|
||||
public void ReadMemory(Process process)
|
||||
{
|
||||
++memoryReadCount;
|
||||
var memoryHelper = new MemoryHelper(process);
|
||||
|
||||
// Snapshot Game Memory
|
||||
snapshot = new MemorySnapshot(process, mainContext.veridx);
|
||||
snapshot = new MemorySnapshot(memoryHelper, mainContext.veridx);
|
||||
|
||||
Update();
|
||||
UpdateDebugArea(process);
|
||||
UpdateEntityData(process);
|
||||
UpdateDebugArea(memoryHelper);
|
||||
UpdateEntityData(memoryHelper);
|
||||
UpdateFps();
|
||||
|
||||
if (snapshot.musicid >= 0) rabiRibiState.lastValidMusicId = snapshot.musicid;
|
||||
prevSnapshot = snapshot;
|
||||
|
||||
memoryHelper.Dispose();
|
||||
}
|
||||
|
||||
private void UpdateFps()
|
||||
@ -284,7 +287,7 @@ namespace rabi_splitter_WPF
|
||||
return MusicChanged() && snapshot.CurrentMusicIs(music);
|
||||
}
|
||||
|
||||
private void UpdateEntityData(Process process)
|
||||
private void UpdateEntityData(MemoryHelper memoryHelper)
|
||||
{
|
||||
// Read entire entity data for specific entity
|
||||
{
|
||||
@ -300,15 +303,15 @@ namespace rabi_splitter_WPF
|
||||
for (int i = 0; i < length; i += 4)
|
||||
{
|
||||
int index = i / 4;
|
||||
int value_int = MemoryHelper.GetMemoryValue<int>(process, baseArrayPtr + i, false);
|
||||
float value_float = MemoryHelper.GetMemoryValue<float>(process, baseArrayPtr + i, false);
|
||||
int value_int = memoryHelper.GetMemoryValue<int>(baseArrayPtr + i, false);
|
||||
float value_float = memoryHelper.GetMemoryValue<float>(baseArrayPtr + i, false);
|
||||
entityStatsList[index].IntVal = value_int;
|
||||
entityStatsList[index].FloatVal = value_float;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDebugArea(Process process)
|
||||
private void UpdateDebugArea(MemoryHelper memoryHelper)
|
||||
{
|
||||
int ptr = snapshot.entityArrayPtr;
|
||||
// List<int> bosses = new List<int>();
|
||||
@ -317,9 +320,9 @@ namespace rabi_splitter_WPF
|
||||
// ptr += StaticData.EnenyEntitySize[mainContext.veridx] * 3;
|
||||
for (var i = 0; i < 50; i++)
|
||||
{
|
||||
debugContext.BossList[i].BossID = MemoryHelper.GetMemoryValue<int>(process,
|
||||
debugContext.BossList[i].BossID = memoryHelper.GetMemoryValue<int>(
|
||||
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false);
|
||||
debugContext.BossList[i].BossHP = MemoryHelper.GetMemoryValue<int>(process,
|
||||
debugContext.BossList[i].BossHP = memoryHelper.GetMemoryValue<int>(
|
||||
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false);
|
||||
ptr += StaticData.EnenyEntitySize[mainContext.veridx];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user