Skip to content

Commit

Permalink
Merge branch 'feature/threadtrapping'
Browse files Browse the repository at this point in the history
  • Loading branch information
GHXX committed Jun 27, 2021
2 parents 819ac3f + 7214363 commit d33025e
Show file tree
Hide file tree
Showing 11 changed files with 353 additions and 70 deletions.
2 changes: 1 addition & 1 deletion DataInterfaceConsole/Actions/BaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal abstract class BaseAction
protected DataInterface di;

public static BaseAction[] GetAndInstantiateAllActions() => typeof(BaseAction).Assembly.GetTypes()
.Where(x => typeof(BaseAction).IsAssignableFrom(x) && typeof(BaseAction) != x)
.Where(x => typeof(BaseAction).IsAssignableFrom(x) && typeof(BaseAction) != x && !x.IsAbstract)
.Select(t => (BaseAction)Activator.CreateInstance(t))
.ToArray();

Expand Down
80 changes: 80 additions & 0 deletions DataInterfaceConsole/Actions/BaseLoadPredefinedVariant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using FiveDChessDataInterface.MemoryHelpers;
using FiveDChessDataInterface.Variants;
using System;
using System.Threading;

namespace DataInterfaceConsole.Actions
{
abstract class BaseLoadPredefinedVariant : BaseAction
{
protected abstract bool UseOnlineVariants { get; }

protected override void Run()
{
AssemblyTrap at = null;
int safeBoardLimit = -1;
try
{
if (!this.di.IsGameRunning()) // if the match isnt running, then use the trap mode to inject it
{
at = this.di.asmHelper.PlaceAssemblyTrap(IntPtr.Add(this.di.GameProcess.MainModule.BaseAddress, 0x289C2));
Console.WriteLine("Main thread trapped. Please start a game, and then check back here.");
}
else
{
safeBoardLimit = this.di.MemLocChessArrayCapacity.GetValue();
Console.WriteLine($"Be advised that injecting a variant with a size of more than {safeBoardLimit} boards during an ongoing match will possibly lead to a crash.\n" +
$"You should consider exiting out to the main menu and rerunning the command.");
}
WaitForIngame();

if (at != null)
Thread.Sleep(1000);

if (this.UseOnlineVariants && !GithubVariantGetter.IsCached)
WriteLineIndented("Getting variants from github...");

var variants = this.UseOnlineVariants ? GithubVariantGetter.GetAllVariants(false, false) : GithubVariantGetter.GetAllVariants(true, true);

WriteLineIndented("Select a variant from the following:" + (at == null ? " (Variants that would may lead to a crash in case they are loaded right now are indicated in yellow)" : ""));
for (int i = 0; i < variants.Length; i++)
{
var originalConsoleColor = Console.ForegroundColor;
if (at == null) // if we are using direct injection, build the variant and check how many boards it has.
{
var boardCount = variants[i].GetGameBuilder().Build().Length;
if (boardCount > safeBoardLimit)
{
Console.ForegroundColor = ConsoleColor.Yellow;
}
}

WriteLineIndented($"{(i + 1).ToString().PadLeft((int)Math.Ceiling(Math.Log10(variants.Length)))}. {variants[i].Name} by {variants[i].Author}");

Console.ForegroundColor = originalConsoleColor;
}

if (int.TryParse(Util.ConsoleReadLineWhile(() => this.di.IsValid()), out int input) && input > 0 && input <= variants.Length)
{
var chosenVariant = variants[input - 1];
WriteLineIndented($"Loading variant '{chosenVariant.Name}'...");
var gb = chosenVariant.GetGameBuilder();
this.di.SetChessBoardArrayFromBuilder(gb);
WriteLineIndented($"Variant loaded and written to memory.");
}
else
{
WriteLineIndented("Invalid input. Not loading any variant.");
}
}
finally
{
if (at != null)
{
WriteLineIndented("Untrapped game thread.");
at.ReleaseTrap();
}
}
}
}
}
31 changes: 5 additions & 26 deletions DataInterfaceConsole/Actions/LoadPredefinedOfflineVariant.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,14 @@
using FiveDChessDataInterface.Variants;
using FiveDChessDataInterface.MemoryHelpers;
using FiveDChessDataInterface.Variants;
using System;
using System.Threading;

namespace DataInterfaceConsole.Actions
{
class LoadPredefinedOfflineVariant : BaseAction
class LoadPredefinedOfflineVariant : BaseLoadPredefinedVariant
{
public override string Name => "Load Predefined Variant [OFFLINE]";

protected override void Run()
{
WaitForIngame();
var variants = GithubVariantGetter.GetAllVariants(true, true);

WriteLineIndented("Select a variant from the following:");
for (int i = 0; i < variants.Length; i++)
{
WriteLineIndented($"{(i + 1).ToString().PadLeft((int)Math.Ceiling(Math.Log10(variants.Length)))}. {variants[i].Name} by {variants[i].Author}");
}

if (int.TryParse(Util.ConsoleReadLineWhile(() => this.di.IsValid()), out int input) && input > 0 && input <= variants.Length)
{
var chosenVariant = variants[input - 1];
WriteLineIndented($"Loading variant '{chosenVariant.Name}'...");
var gb = chosenVariant.GetGameBuilder();
this.di.SetChessBoardArrayFromBuilder(gb);
WriteLineIndented($"Variant loaded and written to memory.");
}
else
{
WriteLineIndented("Invalid input. Not loading any variant.");
}
}
protected override bool UseOnlineVariants => false;
}
}
14 changes: 14 additions & 0 deletions DataInterfaceConsole/Actions/LoadPredefinedOnlineVariant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using FiveDChessDataInterface.MemoryHelpers;
using FiveDChessDataInterface.Variants;
using System;
using System.Threading;

namespace DataInterfaceConsole.Actions
{
class LoadPredefinedOnlineVariant : BaseLoadPredefinedVariant
{
public override string Name => "Load Predefined Variant [ONLINE]";

protected override bool UseOnlineVariants => true;
}
}
38 changes: 0 additions & 38 deletions DataInterfaceConsole/Actions/LoadPredefinedVariant.cs

This file was deleted.

87 changes: 85 additions & 2 deletions DataInterfaceConsoleTest/Examples/ExampleSnippets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,89 @@ public static void DuplicateTimelines(DataInterface di)
Console.WriteLine("Shouldnt run");
}

[CallableExMethod(true, InvokeKind.Startup)]
public static void TrapLocationOnMatchStart(DataInterface di)
{
// TODO autoresolve
// 5dchesswithmultiversetimetravel.exe+91843
var at = di.asmHelper.PlaceAssemblyTrap(IntPtr.Add(di.GameProcess.MainModule.BaseAddress, 0x289C2));
Console.WriteLine("Trap placed!");

SpinWait.SpinUntil(() => di.MemLocChessArrayPointer.GetValue().ToInt64() != 0);
Thread.Sleep(1000);
// other trap addresses:
// 0x91843 -- inside main update loop
// 0x289f0 -- load_variant
// 5dchesswithmultiversetimetravel.exe+289C2 -- post load_variant

var gb2 = new GameBuilderOdd(1, 1);
gb2["0L"].AddEmptyBoard().CopyPrevious(16).AddBoardFromFen("Q");
di.SetChessBoardArrayFromBuilder(gb2);

// demo code
/*
var timelineCnt = 9;
var turnCnt = 8;
var boardHeight = 8;
var boardWidth = 8;
bool useWhite = true;
var piece = "q";
piece = useWhite ? piece.ToUpperInvariant() : piece.ToLowerInvariant();
int subturnOffset = useWhite ? 1 : 0;
var gb2 = new GameBuilderOdd(boardHeight, boardWidth);
var timelineMatrix = Enumerable.Range(-timelineCnt / 2, timelineCnt).Select(x => $"{x}L");
foreach (var tl in timelineMatrix)
{
gb2[tl].AddBoardFromFen(string.Join("/", Enumerable.Repeat(boardWidth.ToString(), boardHeight))).CopyPrevious(turnCnt * 2 - 1 - 1 + subturnOffset);
if (tl == "0L")
{
var leftspace = boardWidth / 2;
var rightspace = boardWidth - 1 - leftspace;
gb2[tl].AddBoardFromFen(string.Join("/", Enumerable.Repeat(boardWidth.ToString(), boardHeight - 1)) + $"/{leftspace}{piece}{rightspace}");
}
else
{
gb2[tl].CopyPrevious();
}
}
di.SetChessBoardArrayFromBuilder(gb2);*/

#region oldcode
//var height = 3;
//var width = 3;
//// example for odd timelines
//var gb = new GameBuilderOdd(height, width);

//gb["-4L"].SetTurnOffset(0, true).AddBoardFromFen("ppp/3/PPP").AddBoardFromFen("ppp/3/PPP").CopyPrevious(10);
//gb["-3L"].SetTurnOffset(1, true).AddBoardFromFen("cyc/3/1P1").AddBoardFromFen("cyc/3/1P1").CopyPrevious(10);
//gb["-2L"].SetTurnOffset(1, true).AddBoardFromFen("cyc/3/1P1").AddBoardFromFen("cyc/3/1P1").CopyPrevious(10);
//gb["-1L"].SetTurnOffset(1, true).AddBoardFromFen("cyc/3/1P1").AddBoardFromFen("cyc/3/1P1").CopyPrevious(10);
//gb["0L"].SetTurnOffset(0, true).AddBoardFromFen("ppp/3/PPP").AddBoardFromFen("ppp/3/PPP").CopyPrevious(10);
//gb["1L"].SetTurnOffset(1, true).AddBoardFromFen("1p1/3/CYC").AddBoardFromFen("1p1/3/CYC").CopyPrevious(10);
//gb["2L"].SetTurnOffset(1, true).AddBoardFromFen("1p1/3/CYC").AddBoardFromFen("1p1/3/CYC").CopyPrevious(10);
//gb["3L"].SetTurnOffset(1, true).AddBoardFromFen("1p1/3/CYC").AddBoardFromFen("1p1/3/CYC").CopyPrevious(10);
//gb["4L"].SetTurnOffset(0, true).AddBoardFromFen("ppp/3/PPP").AddBoardFromFen("ppp/3/PPP").CopyPrevious(10);

//// example for even timelines
//var gb = new GameBuilderEven(height, width);

//gb["-1L"].SetTurnOffset(0, true).AddBoardFromFen("ckc/3/PCP").CopyPrevious(1);
//gb["-0L"].SetTurnOffset(0, true).AddBoardFromFen("ppp/3/PPP").CopyPrevious(1);
//gb["+0L"].SetTurnOffset(0, true).AddBoardFromFen("ppp/3/PPP").CopyPrevious(1);
//gb["+1L"].SetTurnOffset(0, true).AddBoardFromFen("pcp/3/CKC").CopyPrevious(1);
//Console.WriteLine("Old Array ptr:" + di.MemLocChessArrayPointer.ToString());
//di.SetChessBoardArrayFromBuilder(gb);
//Console.WriteLine("New Array ptr:" + di.MemLocChessArrayPointer.ToString());
#endregion

at.ReleaseTrap();
Console.WriteLine("Trap released!");
}

[CallableExMethod(false, InvokeKind.MatchStart)]
public static void ChangeBoardSize(DataInterface di) // changes board size for all boards
{
Expand Down Expand Up @@ -67,7 +150,7 @@ public static void LoadCustomVariant(DataInterface di)
di.SetChessBoardArrayFromBuilder(gb);
}

[CallableExMethod(true, InvokeKind.MatchStart)]
[CallableExMethod(false, InvokeKind.MatchStart)]
public static void LoadPredefinedOnlineVariant(DataInterface di)
{
var variants = GithubVariantGetter.GetAllVariants();
Expand Down Expand Up @@ -297,7 +380,7 @@ public static void AddNewTimelines(DataInterface di)
di.SetChessBoardArray(boards.ToArray());
}

[CallableExMethod(true, InvokeKind.BoardCountChanged | InvokeKind.Startup | InvokeKind.MatchStart | InvokeKind.MatchExited)]
[CallableExMethod(false, InvokeKind.BoardCountChanged | InvokeKind.Startup | InvokeKind.MatchStart | InvokeKind.MatchExited)]
public static void DumpBoardsAndGeneralInfo(DataInterface di)
{
var cbs = di.GetChessBoards();
Expand Down
2 changes: 2 additions & 0 deletions FiveDChessDataInterface/Builders/BaseGameBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public Timeline AddBoardFromFen(string fen)
return this;
}

public Timeline AddEmptyBoard() => AddBoardFromFen(string.Join("/", Enumerable.Repeat(this.boardWidth, this.boardHeight)));

public Timeline CopyPrevious(int repetitionCount = 1)
{
if (!this.Boards.Any())
Expand Down
9 changes: 8 additions & 1 deletion FiveDChessDataInterface/DataInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,15 +445,22 @@ private void SetChessBoardArrayInternal(ChessBoard[] newBoards)
if (newBoards.Length > maxCapacity)
{
this.asmHelper.EnsureArrayCapacity<ChessBoardMemory>(this.MemLocChessArrayPointer, newBoards.Length); // 30*
// one hanging reference ["5dchesswithmultiversetimetravel.exe"+0014BC20]+0x5F0
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x10), 4, newBoards.Length); // 40* MemLocSomeTurnCountOrSomething+0x8 // element size is <= 170 bytes (decimal)
var sz50_60 = 1;
// one hanging reference ["5dchesswithmultiversetimetravel.exe"+0014BAF8]+0x680
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x20), sz50_60, newBoards.Length); // 50*
// two hanging refs ["5dchesswithmultiversetimetravel.exe"+0014BEC0]+0xC90;["5dchesswithmultiversetimetravel.exe"+0014BC30]+F50
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x30), sz50_60, newBoards.Length); // 60*
var szGlobalBitboards = 8;
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x40), szGlobalBitboards, newBoards.Length); // 70*
// one hanging ref ["5dchesswithmultiversetimetravel.exe"+0014BAD8] + 0xBF0
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x50), szGlobalBitboards, newBoards.Length); // 80*
// two hanging refs, but pretty deep in
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x60), szGlobalBitboards, newBoards.Length); // 90*
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x70), szGlobalBitboards, newBoards.Length); // a0*
// one hanging ref ["5dchesswithmultiversetimetravel.exe"+0014BC10]+0x990
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x70), szGlobalBitboards, newBoards.Length); // a0*
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x80), szGlobalBitboards, newBoards.Length); // b0*
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0x90), szGlobalBitboards, newBoards.Length); // c0*
this.asmHelper.EnsureArrayCapacity(this.MemLocChessArrayPointer.WithOffset(0xa0), szGlobalBitboards, newBoards.Length); // d0*
Expand Down
9 changes: 7 additions & 2 deletions FiveDChessDataInterface/MemoryHelpers/AssemblyHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace FiveDChessDataInterface.MemoryHelpers
{
public class AssemblyHelper
{
private readonly IntPtr gameHandle;
private readonly DataInterface di;
internal readonly IntPtr gameHandle;
internal readonly DataInterface di;

public AssemblyHelper(DataInterface di)
{
Expand Down Expand Up @@ -76,10 +76,13 @@ public void EnsureArrayCapacity(MemoryLocation<IntPtr> existingArrayPointerLocat
// otherwise allocate a new array
var newArrayPtr = GameMalloc(newArraySize, true);
var oldStr = existingArrayPointerLocation.ToString();
// copy contents
existingArrayPointerLocation.SetValue(newArrayPtr);
KernelMethods.WriteMemory(this.gameHandle, newArrayPtr, oldContents);
//Console.WriteLine($"Moved array! Old ptr: {oldStr}; New ptr: {existingArrayPointerLocation}");
memLocCapacity.SetValue(newCapacity);
});
}
Expand Down Expand Up @@ -297,5 +300,7 @@ pop rbx

return result;
}

public AssemblyTrap PlaceAssemblyTrap(IntPtr location) => AssemblyTrap.TrapLocation(location, this);
}
}
Loading

0 comments on commit d33025e

Please sign in to comment.