diff --git a/rabi_splitter_WPF/MemoryHelper.cs b/rabi_splitter_WPF/MemoryHelper.cs index 4e72be5..24efef5 100644 --- a/rabi_splitter_WPF/MemoryHelper.cs +++ b/rabi_splitter_WPF/MemoryHelper.cs @@ -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(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(Process process, int addr, bool baseaddr = true) + { + var memoryHelper = new MemoryHelper(process); + return memoryHelper.GetMemoryValue(addr, baseaddr); + } + */ + + public T GetMemoryValue(int addr, bool baseaddr = true) { int datasize; switch (Type.GetTypeCode(typeof(T))) @@ -30,39 +49,40 @@ 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"); } 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))) { @@ -98,9 +118,31 @@ namespace rabi_splitter_WPF default: throw new Exception("not supported"); } - + } + #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 } } diff --git a/rabi_splitter_WPF/MemorySnapshot.cs b/rabi_splitter_WPF/MemorySnapshot.cs index 970dbac..e515dec 100644 --- a/rabi_splitter_WPF/MemorySnapshot.cs +++ b/rabi_splitter_WPF/MemorySnapshot.cs @@ -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(process, StaticData.IGTAddr[veridx]); - playtime = MemoryHelper.GetMemoryValue(process, StaticData.PlaytimeAddr[veridx]); - blackness = MemoryHelper.GetMemoryValue(process, StaticData.BlacknessAddr[veridx]); + t_playtime = memoryHelper.GetMemoryValue(StaticData.IGTAddr[veridx]); + playtime = memoryHelper.GetMemoryValue(StaticData.PlaytimeAddr[veridx]); + blackness = memoryHelper.GetMemoryValue(StaticData.BlacknessAddr[veridx]); - mapid = MemoryHelper.GetMemoryValue(process, StaticData.MapAddress[veridx]); - musicid = MemoryHelper.GetMemoryValue(process, StaticData.MusicAddr[veridx]); - money = MemoryHelper.GetMemoryValue(process, StaticData.MoneyAddress[veridx]); + mapid = memoryHelper.GetMemoryValue(StaticData.MapAddress[veridx]); + musicid = memoryHelper.GetMemoryValue(StaticData.MusicAddr[veridx]); + money = memoryHelper.GetMemoryValue(StaticData.MoneyAddress[veridx]); - carrotXp = MemoryHelper.GetMemoryValue(process, 0xD654BC); - hammerXp = MemoryHelper.GetMemoryValue(process, 0xD654B4); - ribbonXp = MemoryHelper.GetMemoryValue(process, 0xD654B8); - itemPercent = MemoryHelper.GetMemoryValue(process, 0xA730E8); + carrotXp = memoryHelper.GetMemoryValue(0xD654BC); + hammerXp = memoryHelper.GetMemoryValue(0xD654B4); + ribbonXp = memoryHelper.GetMemoryValue(0xD654B8); + itemPercent = memoryHelper.GetMemoryValue(0xA730E8); - minimapPosition = MemoryHelper.GetMemoryValue(process, 0xA72E08); + minimapPosition = memoryHelper.GetMemoryValue(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(process, StaticData.EnenyPtrAddr[veridx]); + entityArrayPtr = memoryHelper.GetMemoryValue(StaticData.EnenyPtrAddr[veridx]); - hp = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x4D8, false); - maxhp = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x4E8, false); + hp = memoryHelper.GetMemoryValue(entityArrayPtr + 0x4D8, false); + maxhp = memoryHelper.GetMemoryValue(entityArrayPtr + 0x4E8, false); - currentSprite = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x654, false); - actionFrame = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x660, false); + currentSprite = memoryHelper.GetMemoryValue(entityArrayPtr + 0x654, false); + actionFrame = memoryHelper.GetMemoryValue(entityArrayPtr + 0x660, false); - amulet = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x52C, false); - boost = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x5DC, false); - mana = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x6B8, false); - stamina = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x5B4, false); + amulet = memoryHelper.GetMemoryValue(entityArrayPtr + 0x52C, false); + boost = memoryHelper.GetMemoryValue(entityArrayPtr + 0x5DC, false); + mana = memoryHelper.GetMemoryValue(entityArrayPtr + 0x6B8, false); + stamina = memoryHelper.GetMemoryValue(entityArrayPtr + 0x5B4, false); - px = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0xC, false); - py = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x10, false); + px = memoryHelper.GetMemoryValue(entityArrayPtr + 0xC, false); + py = memoryHelper.GetMemoryValue(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(process, + int entityId = memoryHelper.GetMemoryValue( currArrayPtr + StaticData.EnenyEnitiyIDOffset[veridx], false); - int entityMaxHp = MemoryHelper.GetMemoryValue(process, + int entityMaxHp = memoryHelper.GetMemoryValue( currArrayPtr + StaticData.EnenyEnitiyMaxHPOffset[veridx], false); if (entityId == 0 && entityMaxHp == 0) break; - int activeFlag = MemoryHelper.GetMemoryValue(process, + int activeFlag = memoryHelper.GetMemoryValue( currArrayPtr + StaticData.EnenyEnitiyIsActiveOffset[veridx], false); - int animationState = MemoryHelper.GetMemoryValue(process, + int animationState = memoryHelper.GetMemoryValue( 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(process, currArrayPtr + StaticData.EnenyEnitiyHPOffset[veridx], false); + boss.hp = memoryHelper.GetMemoryValue(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(process, addr) == 1 ? 1 : 0; + count += memoryHelper.GetMemoryValue(addr) == 1 ? 1 : 0; } return count; } diff --git a/rabi_splitter_WPF/RabiRibiDisplay.cs b/rabi_splitter_WPF/RabiRibiDisplay.cs index 1494a18..07d9305 100644 --- a/rabi_splitter_WPF/RabiRibiDisplay.cs +++ b/rabi_splitter_WPF/RabiRibiDisplay.cs @@ -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(process, baseArrayPtr + i, false); - float value_float = MemoryHelper.GetMemoryValue(process, baseArrayPtr + i, false); + int value_int = memoryHelper.GetMemoryValue(baseArrayPtr + i, false); + float value_float = memoryHelper.GetMemoryValue(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 bosses = new List(); @@ -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(process, + debugContext.BossList[i].BossID = memoryHelper.GetMemoryValue( ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false); - debugContext.BossList[i].BossHP = MemoryHelper.GetMemoryValue(process, + debugContext.BossList[i].BossHP = memoryHelper.GetMemoryValue( ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false); ptr += StaticData.EnenyEntitySize[mainContext.veridx]; }