Skip to content

Commit

Permalink
update 1.0.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
VideoGameRoulette authored Jul 25, 2021
1 parent 569c12b commit ef82aa7
Show file tree
Hide file tree
Showing 15 changed files with 845 additions and 0 deletions.
37 changes: 37 additions & 0 deletions SRTPluginProviderRER2.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SRTPluginProviderRER2", "SRTPluginProviderRER2\SRTPluginProviderRER2.csproj", "{FB803174-8A74-4CC0-8645-B1D6C4F53288}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SRTPluginBase", "..\..\Squirrelies\SRTHost\SRTPluginBase\SRTPluginBase.csproj", "{431972BA-04CE-4D4B-8ECE-80D351B02868}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMemory", "..\..\Squirrelies\ProcessMemory\ProcessMemory\ProcessMemory.csproj", "{C43019D3-C173-4C82-B8A0-6927CE5FCA38}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FB803174-8A74-4CC0-8645-B1D6C4F53288}.Debug|x86.ActiveCfg = Debug|x86
{FB803174-8A74-4CC0-8645-B1D6C4F53288}.Debug|x86.Build.0 = Debug|x86
{FB803174-8A74-4CC0-8645-B1D6C4F53288}.Release|x86.ActiveCfg = Release|x86
{FB803174-8A74-4CC0-8645-B1D6C4F53288}.Release|x86.Build.0 = Release|x86
{431972BA-04CE-4D4B-8ECE-80D351B02868}.Debug|x86.ActiveCfg = Debug|Any CPU
{431972BA-04CE-4D4B-8ECE-80D351B02868}.Debug|x86.Build.0 = Debug|Any CPU
{431972BA-04CE-4D4B-8ECE-80D351B02868}.Release|x86.ActiveCfg = Release|Any CPU
{431972BA-04CE-4D4B-8ECE-80D351B02868}.Release|x86.Build.0 = Release|Any CPU
{C43019D3-C173-4C82-B8A0-6927CE5FCA38}.Debug|x86.ActiveCfg = Debug|x86
{C43019D3-C173-4C82-B8A0-6927CE5FCA38}.Debug|x86.Build.0 = Debug|x86
{C43019D3-C173-4C82-B8A0-6927CE5FCA38}.Release|x86.ActiveCfg = Release|x86
{C43019D3-C173-4C82-B8A0-6927CE5FCA38}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F1CA3A3-4EED-43A9-B230-BC60B2E2ECE9}
EndGlobalSection
EndGlobal
31 changes: 31 additions & 0 deletions SRTPluginProviderRER2/GameHashes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;

namespace SRTPluginProviderRER2
{
/// <summary>
/// SHA256 hashes for the RE5/BIO5 game executables.
/// </summary>
public static class GameHashes
{
private static readonly byte[] rerev2ww_20210702_1 = new byte[32] { 0x41, 0xB4, 0x16, 0x96, 0x75, 0x8C, 0x41, 0x77, 0xE9, 0x33, 0x9F, 0x27, 0xF0, 0x51, 0xAA, 0x4D, 0x72, 0x90, 0x8E, 0xD7, 0x26, 0x3A, 0x82, 0xAA, 0x63, 0xB0, 0x93, 0x3A, 0x3B, 0xCA, 0x9C, 0x77 };
public static GameVersion DetectVersion(string filePath)
{
byte[] checksum;
using (SHA256 hashFunc = SHA256.Create())
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
checksum = hashFunc.ComputeHash(fs);

if (checksum.SequenceEqual(rerev2ww_20210702_1))
{
Console.WriteLine("Steam Version WW Detected");
return GameVersion.REREV2WW_20210702_1;
}

Console.WriteLine("Unknown Version");
return GameVersion.Unknown;
}
}
}
70 changes: 70 additions & 0 deletions SRTPluginProviderRER2/GameMemoryRER2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using SRTPluginProviderRER2.Structs.GameStructs;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;

namespace SRTPluginProviderRER2
{
public class GameMemoryRER2 : IGameMemoryRER2
{
private const string IGT_TIMESPAN_STRING_FORMAT = @"hh\:mm\:ss";
public string GameName => "REREV2";

// Versioninfo
public string VersionInfo => FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;

// BP
public int BP { get => _bp; set => _bp = value; }
internal int _bp;

// Player 1 Stats
public string PlayerName { get => _playerName; set => _playerName = value; }
internal string _playerName;
public GamePlayer Player { get => _player; set => _player = value; }
internal GamePlayer _player;
public int PlayerInventorySize { get => _playerInventorySize; set => _playerInventorySize = value; }
internal int _playerInventorySize;
public GameInventory[] PlayerInventory { get => _playerInventory; set => _playerInventory = value; }
internal GameInventory[] _playerInventory;
public GameInventory[] PlayerEquipped { get => _playerEquipped; set => _playerEquipped = value; }
internal GameInventory[] _playerEquipped;

// Player 2 Stats
public string Player2Name { get => _player2Name; set => _player2Name = value; }
internal string _player2Name;
public GamePlayer Player2 { get => _player2; set => _player2 = value; }
internal GamePlayer _player2;
public int Player2InventorySize { get => _player2InventorySize; set => _player2InventorySize = value; }
internal int _player2InventorySize;
public GameInventory[] Player2Inventory { get => _player2Inventory; set => _player2Inventory = value; }
internal GameInventory[] _player2Inventory;
public GameInventory[] Player2Equipped { get => _player2Equipped; set => _player2Equipped = value; }
internal GameInventory[] _player2Equipped;

public GameEndResults EndResults { get => _endResults; set => _endResults = value; }
internal GameEndResults _endResults;

public int EnemyCount { get => _enemyCount; set => _enemyCount = value; }
internal int _enemyCount;
public GameEnemy[] EnemyHealth { get => _enemyHealth; set => _enemyHealth = value; }
internal GameEnemy[] _enemyHealth;

public TimeSpan IGTTimeSpan
{
get
{
TimeSpan timespanIGT;

if (EndResults.ClearTime >= 0f)
timespanIGT = TimeSpan.FromSeconds(EndResults.ClearTime);
else
timespanIGT = new TimeSpan();

return timespanIGT;
}
}

public string IGTFormattedString => IGTTimeSpan.ToString(IGT_TIMESPAN_STRING_FORMAT, CultureInfo.InvariantCulture);
}
}
235 changes: 235 additions & 0 deletions SRTPluginProviderRER2/GameMemoryRER2Scanner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
using ProcessMemory;
using SRTPluginProviderRER2.Structs.GameStructs;
using System;
using System.Diagnostics;

namespace SRTPluginProviderRER2
{
internal unsafe class GameMemoryRER2Scanner : IDisposable
{
private readonly int MAX_ENTITIES = 16;
private readonly int MAX_ITEMS = 20;
private readonly int MAX_EQUIP = 4;

// Variables
private ProcessMemoryHandler memoryAccess;
private GameMemoryRER2 gameMemoryValues;
public bool HasScanned;
public bool ProcessRunning => memoryAccess != null && memoryAccess.ProcessRunning;
public int ProcessExitCode => (memoryAccess != null) ? memoryAccess.ProcessExitCode : 0;

// Pointer Address Variables
private int pointerAddressPlayer;
private int pointerAddressStats;
private int pointerAddressInventory;
private int pointerAddressEnemies;

// Pointer Classes
private IntPtr BaseAddress { get; set; }
private MultilevelPointer PointerHP { get; set; }
private MultilevelPointer PointerPlayerID { get; set; }
private MultilevelPointer PointerHP2 { get; set; }
private MultilevelPointer PointerPlayer2ID { get; set; }
private MultilevelPointer PointerStats { get; set; }

private MultilevelPointer PointerInventorySize { get; set; }
private MultilevelPointer PointerInventorySize2 { get; set; }
private MultilevelPointer[] PointerInventory { get; set; }
private MultilevelPointer[] PointerInventory2 { get; set; }
private MultilevelPointer[] PointerEquipped { get; set; }
private MultilevelPointer[] PointerEquipped2 { get; set; }

private MultilevelPointer PointerEnemyCount { get; set; }
private MultilevelPointer[] PointerEnemyEntires { get; set; }

internal GameMemoryRER2Scanner(Process process = null)
{
gameMemoryValues = new GameMemoryRER2();
if (process != null)
Initialize(process);
}

internal unsafe void Initialize(Process process)
{
if (process == null)
return; // Do not continue if this is null.

GameHashes.DetectVersion(process.MainModule.FileName);
SelectPointerAddresses();

int pid = GetProcessId(process).Value;
memoryAccess = new ProcessMemoryHandler(pid);
if (ProcessRunning)
{
BaseAddress = NativeWrappers.GetProcessBaseAddress(pid, PInvoke.ListModules.LIST_MODULES_32BIT); // Bypass .NET's managed solution for getting this and attempt to get this info ourselves via PInvoke since some users are getting 299 PARTIAL COPY when they seemingly shouldn't.

//POINTERS
PointerHP = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressPlayer), 0x20);
PointerPlayerID = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressPlayer), 0x20, 0x0, 0x10, 0x1);
PointerHP2 = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressPlayer), 0x24);
PointerPlayer2ID = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressPlayer), 0x24, 0x0, 0x10, 0x1);
PointerStats = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressStats));

gameMemoryValues._playerInventory = new GameInventory[MAX_ITEMS];
gameMemoryValues._player2Inventory = new GameInventory[MAX_ITEMS];
PointerInventory = new MultilevelPointer[MAX_ITEMS];
PointerInventory2 = new MultilevelPointer[MAX_ITEMS];
PointerInventorySize = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x150);
PointerInventorySize2 = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x154);
var position = 0;
for (var i = 0; i < MAX_ITEMS; i++)
{
position = i * 0x4 + 0xC;
gameMemoryValues._playerInventory[i] = new GameInventory();
gameMemoryValues._player2Inventory[i] = new GameInventory();
PointerInventory[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x150, position);
PointerInventory2[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x154, position);
}

gameMemoryValues._playerEquipped = new GameInventory[MAX_EQUIP];
gameMemoryValues._player2Equipped = new GameInventory[MAX_EQUIP];
PointerEquipped = new MultilevelPointer[MAX_EQUIP];
PointerEquipped2 = new MultilevelPointer[MAX_EQUIP];
for (var i = 0; i < MAX_EQUIP; i++)
{
position = i * 0x4 + 0x5C;
gameMemoryValues._playerEquipped[i] = new GameInventory();
gameMemoryValues._player2Equipped[i] = new GameInventory();
PointerEquipped[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x150, position);
PointerEquipped2[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressInventory), 0x30, 0x154, position);
}

gameMemoryValues._enemyHealth = new GameEnemy[MAX_ENTITIES];
PointerEnemyEntires = new MultilevelPointer[MAX_ENTITIES];
PointerEnemyCount = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressEnemies), 0x3C, 0x7C);
for (var i = 0; i < MAX_ENTITIES; i++)
{
position = i * 0x4 + 0x30;
PointerEnemyEntires[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(BaseAddress, pointerAddressEnemies), 0x3C, 0x7C, position);
}
}
}

private void SelectPointerAddresses()
{
pointerAddressPlayer = 0x1167EAC;
pointerAddressStats = 0x117D120;
pointerAddressInventory = 0x117D1E8;
pointerAddressEnemies = 0x1161E70;
}

internal void UpdatePointers()
{
PointerHP.UpdatePointers();
PointerPlayerID.UpdatePointers();
PointerHP2.UpdatePointers();
PointerPlayer2ID.UpdatePointers();
PointerStats.UpdatePointers();

PointerInventorySize.UpdatePointers();
PointerInventorySize2.UpdatePointers();

// Player Inventories
for (var i = 0; i < MAX_ITEMS; i++)
{
PointerInventory[i].UpdatePointers();
PointerInventory2[i].UpdatePointers();
}

// Player Equippment
for (var i = 0; i < MAX_EQUIP; i++)
{
PointerEquipped[i].UpdatePointers();
PointerEquipped2[i].UpdatePointers();
}

PointerEnemyCount.UpdatePointers();
for (var i = 0; i < MAX_ENTITIES; i++)
{
PointerEnemyEntires[i].UpdatePointers();
}
}

internal unsafe IGameMemoryRER2 Refresh()
{
//
gameMemoryValues._bp = PointerStats.DerefInt(0xE88);

// Player 1
gameMemoryValues._player = PointerHP.Deref<GamePlayer>(0x1A00);
gameMemoryValues._playerName = PointerPlayerID.Deref<GamePlayerID>(0x1C).Name;

// Player 2
gameMemoryValues._player2 = PointerHP2.Deref<GamePlayer>(0x1A00);
gameMemoryValues._player2Name = PointerPlayer2ID.Deref<GamePlayerID>(0x1C).Name;

// Game Statistics
gameMemoryValues._endResults = PointerStats.Deref<GameEndResults>(0x1403F0);

// Player Inventories
gameMemoryValues._playerInventorySize = PointerInventorySize.DerefInt(0x8);
gameMemoryValues._player2InventorySize = PointerInventorySize2.DerefInt(0x8);

for (var i = 0; i < MAX_ITEMS; i++)
{
gameMemoryValues._playerInventory[i] = PointerInventory[i].Deref<GameInventory>(0x0);
gameMemoryValues._player2Inventory[i] = PointerInventory2[i].Deref<GameInventory>(0x0);
}

// Player Equippment
for (var i = 0; i < MAX_EQUIP; i++)
{
gameMemoryValues._playerEquipped[i] = PointerEquipped[i].Deref<GameInventory>(0x0);
gameMemoryValues._player2Equipped[i] = PointerEquipped2[i].Deref<GameInventory>(0x0);
}

gameMemoryValues._enemyCount = PointerEnemyCount.DerefInt(0x2C);
for (var i = 0; i < MAX_ENTITIES; i++)
{
gameMemoryValues._enemyHealth[i] = PointerEnemyEntires[i].Deref<GameEnemy>(0x1A00);
}

HasScanned = true;
return gameMemoryValues;
}

private int? GetProcessId(Process process) => process?.Id;

#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
if (memoryAccess != null)
memoryAccess.Dispose();
}

// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.

disposedValue = true;
}
}

// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~REmake1Memory() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }

// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
}
8 changes: 8 additions & 0 deletions SRTPluginProviderRER2/GameVersion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SRTPluginProviderRER2
{
public enum GameVersion : int
{
Unknown,
REREV2WW_20210702_1
}
}
Loading

0 comments on commit ef82aa7

Please sign in to comment.